Revert commit 24722db3fc92

Rc'ing types instead of cloning does improve performance of passes and other
tree-manip-stuff by roughly 10%, but is inconvenient enough that it's prolly
not worth it.  Interning them would work better and also be easier since it'd
make all our types Copy.

But that attempt also had a bit of nice code cleanup in it, so I've
tried to preserve it.
M benches/basic.rs +7 -33
@@ 66,7 66,7 @@ end
     buf
 }
 
-fn bench_with_rust_backend(c: &mut Criterion) {
+fn bench_compile(c: &mut Criterion) {
     let code = gen_dumb_test_code(103);
     let lines = code.lines().count();
     let name = format!("compile {}ish lines to Rust", lines);

          
@@ 81,7 81,6 @@ fn bench_with_rust_backend(c: &mut Crite
         b.iter(|| compile("criterion.gt", black_box(&code), backend::Backend::Rust))
     });
 
-    /*
     let code = gen_dumb_test_code(103 * 16);
     let lines = code.lines().count();
     let name = format!("compile {}ish lines", lines);

          
@@ 94,30 93,6 @@ fn bench_with_rust_backend(c: &mut Crite
             )
         })
     });
-    */
-}
-
-fn bench_with_null_backend(c: &mut Criterion) {
-    let code = gen_dumb_test_code(103);
-    let lines = code.lines().count();
-    let name = format!("compile {}ish lines to nothing", lines);
-    c.bench_function(&name, |b| {
-        b.iter(|| compile("criterion.gt", black_box(&code), backend::Backend::Null))
-    });
-
-    let code = gen_dumb_test_code(103 * 8);
-    let lines = code.lines().count();
-    let name = format!("compile {}ish lines to nothing", lines);
-    c.bench_function(&name, |b| {
-        b.iter(|| compile("criterion.gt", black_box(&code), backend::Backend::Null))
-    });
-
-    let code = gen_dumb_test_code(103 * 16);
-    let lines = code.lines().count();
-    let name = format!("compile {}ish lines to nothing", lines);
-    c.bench_function(&name, |b| {
-        b.iter(|| compile("criterion.gt", black_box(&code), backend::Backend::Rust))
-    });
 }
 
 fn bench_stages(c: &mut Criterion) {

          
@@ 161,15 136,14 @@ fn bench_stages(c: &mut Criterion) {
     });
 
     let hir = passes::run_typechecked_passes(hir, tck);
-    c.bench_function("codegen", |b| {
+    c.bench_function("codegen to Rust", |b| {
         b.iter(|| backend::output(backend::Backend::Rust, black_box(&hir), black_box(tck)))
     });
+
+    c.bench_function("codegen to null", |b| {
+        b.iter(|| backend::output(backend::Backend::Null, black_box(&hir), black_box(tck)))
+    });
 }
 
-criterion_group!(
-    benches,
-    //bench_with_rust_backend,
-    //bench_with_null_backend,
-    bench_stages
-);
+criterion_group!(benches, bench_compile, bench_stages);
 criterion_main!(benches);

          
M src/ast.rs +7 -7
@@ 96,11 96,11 @@ pub struct IfCase {
 #[derive(Debug, Clone, PartialEq)]
 pub struct Signature {
     /// Parameters
-    pub params: Arc<Vec<(Sym, Type)>>,
+    pub params: Vec<(Sym, Type)>,
     /// Return type
     pub rettype: Type,
     /// Type parameters
-    pub typeparams: Arc<Vec<Type>>,
+    pub typeparams: Vec<Type>,
 }
 
 impl Signature {

          
@@ 108,8 108,8 @@ impl Signature {
     pub fn to_type(&self) -> Type {
         let paramtypes = self.params.iter().map(|(_nm, ty)| ty.clone()).collect();
         Type::Func(
-            Arc::new(paramtypes),
-            Arc::new(self.rettype.clone()),
+            paramtypes,
+            Box::new(self.rettype.clone()),
             self.typeparams.clone(),
         )
     }

          
@@ 150,14 150,14 @@ impl Signature {
                 let new_params = self
                     .params
                     .iter()
-                    .zip(params.as_ref())
+                    .zip(params)
                     .map(|((nm, _t1), t2)| (*nm, t2.clone()))
                     .collect();
                 let new_rettype = rettype.clone();
                 let new_type_params = typeparams.clone();
                 Self {
-                    params: Arc::new(new_params),
-                    rettype: new_rettype.as_ref().clone(),
+                    params: new_params,
+                    rettype: *new_rettype,
                     typeparams: new_type_params,
                 }
             }

          
M src/backend/rust.rs +4 -4
@@ 44,7 44,7 @@ fn compile_typename(t: &Type) -> Cow<'st
         Named(s, types) if s == &Sym::new("Tuple") => {
             trace!("Compiling tuple {:?}...", t);
             let mut accm = String::from("(");
-            for typ in &**types {
+            for typ in types {
                 accm += &compile_typename(typ);
                 accm += ", ";
             }

          
@@ 68,7 68,7 @@ fn compile_typename(t: &Type) -> Cow<'st
             }
             */
             accm += "(";
-            for p in &**params {
+            for p in params {
                 accm += &compile_typename(p);
                 accm += ", ";
             }

          
@@ 149,7 149,7 @@ fn compile_typename(t: &Type) -> Cow<'st
 /// Driver that turns a pile of Ir into Rust code.
 pub(super) fn output(lir: &hir::Ir, tck: &Tck) -> Vec<u8> {
     let mut output = Vec::new();
-    for builtin in &*builtins::all() {
+    for builtin in &*builtins::BUILTINS {
         output.extend(builtin.code[&backend::Backend::Rust].as_bytes());
     }
     for decl in lir.decls.iter() {

          
@@ 223,7 223,7 @@ fn compile_decl(w: &mut impl Write, decl
                         params.iter().map(|sym| (*sym.val()).clone()).collect();
                     let args = param_strings.join(", ");
                     writeln!(w, "pub enum {}<{}> {{ ", nstr, args)?;
-                    for (nm, ty) in &**body {
+                    for (nm, ty) in body {
                         writeln!(w, "    {} ({}),", nm, compile_typename(ty))?;
                     }
                     writeln!(w, "}}")?;

          
M src/bin/garnetfmt.rs +1 -0
@@ 39,6 39,7 @@ fn main() -> io::Result<()> {
     // anything
     let formatted_data = &formatted_src.into_inner();
     let formatted_str = String::from_utf8_lossy(formatted_data);
+    println!("{}", formatted_str);
     let formatted_ast = {
         let mut parser = parser::Parser::new(filename, &formatted_str);
         parser.parse()

          
M src/builtins.rs +49 -45
@@ 6,6 6,8 @@ 
 
 use std::collections::BTreeMap;
 
+use once_cell::sync::Lazy;
+
 use crate::backend::Backend;
 use crate::*;
 

          
@@ 20,6 22,8 @@ pub struct Builtin {
     pub code: BTreeMap<Backend, String>,
 }
 
+pub static BUILTINS: Lazy<Vec<Builtin>> = Lazy::new(Builtin::all);
+
 impl Builtin {
     /// Generate all appropriate methods for the given numeric type.
     /// Right now we just stick em in the toplevel with constructed names,

          
@@ 104,99 108,99 @@ fn __{name}_to_u32(x: {name}) -> u32 {{
         vec![
             Builtin {
                 name: Sym::new(format!("__println_{name}")),
-                sig: Type::function(&vec![ty.clone()], &Type::unit(), &vec![]),
+                sig: Type::Func(vec![ty.clone()], Box::new(Type::unit()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, println)]),
             },
             Builtin {
                 name: Sym::new(format!("__band_{name}")),
-                sig: Type::function(&vec![ty.clone(), ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, band)]),
             },
             Builtin {
                 name: Sym::new(format!("__bor_{name}")),
-                sig: Type::function(&vec![ty.clone(), ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bor)]),
             },
             Builtin {
                 name: Sym::new(format!("__bxor_{name}")),
-                sig: Type::function(&vec![ty.clone(), ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bxor)]),
             },
             Builtin {
                 name: Sym::new(format!("__bnot_{name}")),
-                sig: Type::function(&vec![ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bnot)]),
             },
             Builtin {
                 name: Sym::new(format!("__rshift_{name}")),
-                sig: Type::function(&vec![ty.clone(), ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, rshift)]),
             },
             Builtin {
                 name: Sym::new(format!("__lshift_{name}")),
-                sig: Type::function(&vec![ty.clone(), ty.clone()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, lshift)]),
             },
             Builtin {
                 name: Sym::new(format!("__rol_{name}")),
-                sig: Type::function(&vec![ty.clone(), Type::i32()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), Type::i32()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, rol)]),
             },
             Builtin {
                 name: Sym::new(format!("__ror_{name}")),
-                sig: Type::function(&vec![ty.clone(), Type::i32()], &ty.clone(), &vec![]),
+                sig: Type::Func(vec![ty.clone(), Type::i32()], Box::new(ty.clone()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, ror)]),
             },
             Builtin {
                 name: Sym::new(format!("__{name}_to_i32")),
-                sig: Type::function(&vec![ty.clone()], &Type::i32(), &vec![]),
+                sig: Type::Func(vec![ty.clone()], Box::new(Type::i32()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, cast_i32)]),
             },
             Builtin {
                 name: Sym::new(format!("__{name}_to_u32")),
-                sig: Type::function(&vec![ty.clone()], &Type::u32(), &vec![]),
+                sig: Type::Func(vec![ty.clone()], Box::new(Type::u32()), vec![]),
                 code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, cast_u32)]),
             },
         ]
     }
-}
-/// A function that returns all the compiler builtin info.  Just
-/// use the `BUILTINS` global instead, this is basically here
-/// to initialize it.
-pub fn all() -> Vec<Builtin> {
-    let rust_println = r#"fn __println(x: i32) {
+    /// A function that returns all the compiler builtin info.  Just
+    /// use the `BUILTINS` global instead, this is basically here
+    /// to initialize it.
+    fn all() -> Vec<Builtin> {
+        let rust_println = r#"fn __println(x: i32) {
     println!("{}", x);
 }"#;
-    let rust_println_bool = r#"
+        let rust_println_bool = r#"
 fn __println_bool(x: bool) {
     println!("{}", x);
 }"#;
 
-    let mut funcs = vec![
-        Builtin {
-            name: Sym::new("__println"),
-            sig: Type::function(&vec![Type::i32()], &Type::unit(), &vec![]),
-            code: BTreeMap::from([
-                (Backend::Null, "".into()),
-                (Backend::Rust, rust_println.into()),
-            ]),
-        },
-        Builtin {
-            name: Sym::new("__println_bool"),
-            sig: Type::function(&vec![Type::bool()], &Type::unit(), &vec![]),
-            code: BTreeMap::from([
-                (Backend::Null, "".into()),
-                (Backend::Rust, rust_println_bool.into()),
-            ]),
-        },
-    ];
-    funcs.extend(Builtin::generate_numerics_for("i8", Type::i8()));
-    funcs.extend(Builtin::generate_numerics_for("i16", Type::i16()));
-    funcs.extend(Builtin::generate_numerics_for("i32", Type::i32()));
-    funcs.extend(Builtin::generate_numerics_for("i64", Type::i64()));
-    funcs.extend(Builtin::generate_numerics_for("u8", Type::u8()));
-    funcs.extend(Builtin::generate_numerics_for("u16", Type::u16()));
-    funcs.extend(Builtin::generate_numerics_for("u32", Type::u32()));
-    funcs.extend(Builtin::generate_numerics_for("u64", Type::u64()));
-    funcs
+        let mut funcs = vec![
+            Builtin {
+                name: Sym::new("__println"),
+                sig: Type::Func(vec![Type::i32()], Box::new(Type::unit()), vec![]),
+                code: BTreeMap::from([
+                    (Backend::Null, "".into()),
+                    (Backend::Rust, rust_println.into()),
+                ]),
+            },
+            Builtin {
+                name: Sym::new("__println_bool"),
+                sig: Type::Func(vec![Type::bool()], Box::new(Type::unit()), vec![]),
+                code: BTreeMap::from([
+                    (Backend::Null, "".into()),
+                    (Backend::Rust, rust_println_bool.into()),
+                ]),
+            },
+        ];
+        funcs.extend(Self::generate_numerics_for("i8", Type::i8()));
+        funcs.extend(Self::generate_numerics_for("i16", Type::i16()));
+        funcs.extend(Self::generate_numerics_for("i32", Type::i32()));
+        funcs.extend(Self::generate_numerics_for("i64", Type::i64()));
+        funcs.extend(Self::generate_numerics_for("u8", Type::u8()));
+        funcs.extend(Self::generate_numerics_for("u16", Type::u16()));
+        funcs.extend(Self::generate_numerics_for("u32", Type::u32()));
+        funcs.extend(Self::generate_numerics_for("u64", Type::u64()));
+        funcs
+    }
 }

          
M src/hir.rs +11 -12
@@ 768,10 768,10 @@ fn lower_typedef(accm: &mut Vec<Decl>, n
             let struct_signature = ts
                 .iter()
                 //.map(|(enumname, _enumval)| (*enumname, ty.clone()))
-                .map(|(enumname, _enumval)| (*enumname, Type::Named(name, Arc::new(vec![]))))
+                .map(|(enumname, _enumval)| (*enumname, Type::Named(name, vec![])))
                 .collect();
             // Enums cannot have type parameters, so this works.
-            let init_type = Type::Struct(Arc::new(struct_signature), Arc::new(vec![]));
+            let init_type = Type::Struct(struct_signature, vec![]);
             let new_constdef = Const {
                 name,
                 typ: init_type,

          
@@ 798,7 798,7 @@ fn lower_typedef(accm: &mut Vec<Decl>, n
                 .map(|(variant_name, variant_type)| {
                     let paramname = Sym::new("x");
                     let signature = ast::Signature {
-                        params: Arc::new(vec![(paramname, variant_type.clone())]),
+                        params: vec![(paramname, variant_type.clone())],
                         rettype: Type::Named(name, generics.clone()),
                         typeparams: generics.clone(),
                     };

          
@@ 822,15 822,15 @@ fn lower_typedef(accm: &mut Vec<Decl>, n
                     // `fn(variant_type) name`
                     (
                         *variant_name,
-                        Type::function(
-                            &[variant_type.clone()],
-                            &Type::Named(name, generics.clone()),
-                            &generics,
+                        Type::Func(
+                            vec![variant_type.clone()],
+                            Box::new(Type::Named(name, generics.clone())),
+                            generics.clone(),
                         ),
                     )
                 })
                 .collect();
-            let struct_type = Type::Struct(Arc::new(struct_typebody), generics.clone());
+            let struct_type = Type::Struct(struct_typebody, generics.clone());
             let new_constdef = Const {
                 name: name.to_owned(),
                 typ: struct_type,

          
@@ 843,10 843,9 @@ fn lower_typedef(accm: &mut Vec<Decl>, n
         other => {
             let s = Sym::new("x");
             trace!("Lowering params {:?}", params);
-            let type_params: Arc<Vec<_>> =
-                Arc::new(params.iter().map(|s| Type::Generic(*s)).collect());
+            let type_params: Vec<_> = params.iter().map(|s| Type::Generic(*s)).collect();
             let signature = ast::Signature {
-                params: Arc::new(vec![(s, other.clone())]),
+                params: vec![(s, other.clone())],
                 rettype: Type::Named(name.to_owned(), type_params.clone()),
                 typeparams: type_params.clone(),
             };

          
@@ 854,7 853,7 @@ fn lower_typedef(accm: &mut Vec<Decl>, n
             // in a type constructor
             let body = vec![ExprNode::new(Expr::TypeCtor {
                 name,
-                type_params: type_params.to_vec(),
+                type_params,
                 body: ExprNode::new(Expr::Var { name: s }),
             })];
             //println!("{} is {:#?}", variant_name, e);

          
M src/lib.rs +24 -28
@@ 74,26 74,26 @@ pub enum Type {
     /// Never type, the type of an infinite loop
     Never,
     /// A C-like enum, and the integer values it corresponds to
-    Enum(Arc<Vec<(Sym, i32)>>),
+    Enum(Vec<(Sym, i32)>),
     /// A nominal type of some kind; may be built-in (like Tuple)
     /// or user-defined.
-    Named(Sym, Arc<Vec<Type>>),
+    Named(Sym, Vec<Type>),
     /// A function pointer.
     ///
     /// The contents are arg types, return types, type parameters
-    Func(Arc<Vec<Type>>, Arc<Type>, Arc<Vec<Type>>),
+    Func(Vec<Type>, Box<Type>, Vec<Type>),
     /// An anonymous struct.  The vec is type parameters.
-    Struct(Arc<BTreeMap<Sym, Type>>, Arc<Vec<Type>>),
+    Struct(BTreeMap<Sym, Type>, Vec<Type>),
     /// Sum type.
     ///
     /// Like structs, contains a list of type parameters.
-    Sum(Arc<BTreeMap<Sym, Type>>, Arc<Vec<Type>>),
+    Sum(BTreeMap<Sym, Type>, Vec<Type>),
     /// Arrays are just a type and a number.
-    Array(Arc<Type>, usize),
+    Array(Box<Type>, usize),
     /// A generic type parameter that has been given an explicit name.
     Generic(Sym),
     /// Unique borrow
-    Uniq(Arc<Type>),
+    Uniq(Box<Type>),
 }
 
 impl Type {

          
@@ 126,18 126,18 @@ impl Type {
                     helper(rettype, accm)
                 }
                 Type::Struct(body, generics) => {
-                    for (_, ty) in &**body {
+                    for (_, ty) in body {
                         helper(ty, accm);
                     }
-                    for g in &**generics {
+                    for g in generics {
                         helper(g, accm);
                     }
                 }
                 Type::Sum(body, generics) => {
-                    for (_, ty) in &**body {
+                    for (_, ty) in body {
                         helper(ty, accm);
                     }
-                    for g in &**generics {
+                    for g in generics {
                         helper(g, accm);
                     }
                 }

          
@@ 238,29 238,29 @@ impl Type {
 
     /// Shortcut for getting the type for Unit
     pub fn unit() -> Self {
-        Self::Named(Sym::new("Tuple"), Arc::new(vec![]))
+        Self::Named(Sym::new("Tuple"), vec![])
     }
 
     /// Shortcut for getting the type for Never
     pub fn never() -> Self {
-        Self::Named(Sym::new("Never"), Arc::new(vec![]))
+        Self::Named(Sym::new("Never"), vec![])
     }
 
     /// Create a Tuple with the given values
-    pub fn tuple(args: Arc<Vec<Self>>) -> Self {
+    pub fn tuple(args: Vec<Self>) -> Self {
         Self::Named(Sym::new("Tuple"), args)
     }
 
     /// Used in some tests
     pub fn array(t: &Type, len: usize) -> Self {
-        Self::Array(Arc::new(t.clone()), len)
+        Self::Array(Box::new(t.clone()), len)
     }
 
     fn function(params: &[Type], rettype: &Type, generics: &[Type]) -> Self {
         Type::Func(
-            Arc::new(Vec::from(params)),
-            Arc::new(rettype.clone()),
-            Arc::new(Vec::from(generics)),
+            Vec::from(params),
+            Box::new(rettype.clone()),
+            Vec::from(generics),
         )
     }
 

          
@@ 446,11 446,11 @@ impl Type {
                 if !body1.keys().eq(body2.keys()) {
                     panic!("subst for sum type had non-matching keys")
                 }
-                for ((_nm1, t1), (_nm2, t2)) in (&**body1).iter().zip(&**body2) {
+                for ((_nm1, t1), (_nm2, t2)) in body1.iter().zip(body2) {
                     t1._find_substs(t2, substitutions);
                 }
 
-                for (p1, p2) in (&**generics1).iter().zip(&**generics2) {
+                for (p1, p2) in (&**generics1).iter().zip(generics2) {
                     p1._find_substs(p2, substitutions);
                 }
             }

          
@@ 488,15 488,11 @@ impl Type {
                 if typeparams1.len() > 0 {
                     todo!("Hsfjkdslfjs");
                 }
-                Type::Func(
-                    Arc::new(new_params),
-                    Arc::new(new_rettype),
-                    Arc::new(vec![]),
-                )
+                Type::Func(new_params, Box::new(new_rettype), vec![])
             }
             Type::Named(n1, args1) => {
                 let new_args = args1.iter().map(|p1| p1._apply_substs(substs)).collect();
-                Type::Named(*n1, Arc::new(new_args))
+                Type::Named(*n1, new_args)
             }
             Type::Struct(_, _) => unreachable!("see other unreachable in substitute()"),
             Type::Sum(body, generics) => {

          
@@ 505,9 501,9 @@ impl Type {
                     .map(|(nm, ty)| (*nm, ty._apply_substs(substs)))
                     .collect();
                 let new_generics = generics.iter().map(|p1| p1._apply_substs(substs)).collect();
-                Type::Sum(Arc::new(new_body), Arc::new(new_generics))
+                Type::Sum(new_body, new_generics)
             }
-            Type::Array(body, len) => Type::Array(Arc::new(body._apply_substs(substs)), *len),
+            Type::Array(body, len) => Type::Array(Box::new(body._apply_substs(substs)), *len),
             Type::Generic(nm) => substs
                 .get(&nm)
                 .unwrap_or_else(|| panic!("No substitution found for generic named {}!", nm))

          
M src/parser.rs +11 -11
@@ 706,9 706,9 @@ impl<'input> Parser<'input> {
         let (params, typeparams) = self.parse_fn_args();
         let rettype = self.try_parse_type().unwrap_or(Type::unit());
         ast::Signature {
-            params: Arc::new(params),
+            params,
             rettype,
-            typeparams: Arc::new(typeparams),
+            typeparams,
         }
     }
 

          
@@ 890,19 890,19 @@ impl<'input> Parser<'input> {
             }
         });
         self.expect(T::RBrace);
-        Some(Type::tuple(Arc::new(body)))
+        Some(Type::tuple(body))
     }
 
     fn try_parse_struct_type(&mut self) -> Option<Type> {
         let (fields, type_params) = self.parse_struct_fields();
         self.expect(T::End);
-        Some(Type::Struct(Arc::new(fields), Arc::new(type_params)))
+        Some(Type::Struct(fields, type_params))
     }
 
     fn parse_enum_type(&mut self) -> Type {
         let variants = self.parse_enum_fields();
         self.expect(T::End);
-        Type::Enum(Arc::new(variants))
+        Type::Enum(variants)
     }
 
     /// isomorphic-ish with parse_type_list()

          
@@ 941,7 941,7 @@ impl<'input> Parser<'input> {
             .map(|ty| Type::Generic(ty))
             .collect();
         */
-        Type::Sum(Arc::new(fields), Arc::new(generics))
+        Type::Sum(fields, generics)
     }
 
     fn parse_exprs(&mut self) -> Vec<ast::Expr> {

          
@@ 1384,7 1384,7 @@ impl<'input> Parser<'input> {
                     } else {
                         vec![]
                     };
-                    Type::Named(Sym::new(s), Arc::new(type_params))
+                    Type::Named(Sym::new(s), type_params)
                 }
             }
             T::At => {

          
@@ 1401,11 1401,11 @@ impl<'input> Parser<'input> {
                 assert!(len >= 0);
                 self.expect(T::RBracket);
                 let inner = self.parse_type();
-                Type::Array(Arc::new(inner), len as usize)
+                Type::Array(Box::new(inner), len as usize)
             }
             T::Ampersand => {
                 let next = self.try_parse_type()?;
-                Type::Uniq(Arc::new(next))
+                Type::Uniq(Box::new(next))
             }
             _ => {
                 // Wind the parse stream back to wherever we started

          
@@ 1554,9 1554,9 @@ mod tests {
             ast::Decl::Function {
                 name: Sym::new("foo"),
                 signature: ast::Signature {
-                    params: Arc::new(vec![(Sym::new("x"), i32_t.clone())]),
+                    params: vec![(Sym::new("x"), i32_t.clone())],
                     rettype: i32_t,
-                    typeparams: Arc::new(vec![]),
+                    typeparams: vec![],
                 },
                 body: vec![Expr::int(9)],
                 doc_comment: vec![],

          
M src/passes.rs +15 -18
@@ 319,8 319,8 @@ fn decl_map(
     }
 }
 
-fn types_map(typs: Arc<Vec<Type>>, f: &mut dyn FnMut(Type) -> Type) -> Arc<Vec<Type>> {
-    Arc::new(typs.iter().cloned().map(|t| type_map(t, f)).collect())
+fn types_map(typs: Vec<Type>, f: &mut dyn FnMut(Type) -> Type) -> Vec<Type> {
+    typs.into_iter().map(|t| type_map(t, f)).collect()
 }
 
 /// Recursion scheme to turn one type into another.

          
@@ 330,17 330,15 @@ fn type_map(typ: Type, f: &mut dyn FnMut
     /// it generic over any iterator, if we want to make life even harder for
     /// ourself.
     fn types_map_btree<K>(
-        typs: Arc<BTreeMap<K, Type>>,
+        typs: BTreeMap<K, Type>,
         f: &mut dyn FnMut(Type) -> Type,
-    ) -> Arc<BTreeMap<K, Type>>
+    ) -> BTreeMap<K, Type>
     where
-        K: Ord + Clone,
+        K: Ord,
     {
-        Arc::new(
-            typs.iter()
-                .map(|(key, ty)| (key.clone(), type_map(ty.clone(), f)))
-                .collect(),
-        )
+        typs.into_iter()
+            .map(|(key, ty)| (key, type_map(ty, f)))
+            .collect()
     }
     let res = match typ {
         Type::Struct(fields, generics) => {

          
@@ 351,12 349,12 @@ fn type_map(typ: Type, f: &mut dyn FnMut
             let new_fields = types_map_btree(fields, f);
             Type::Sum(new_fields, generics)
         }
-        Type::Array(ty, len) => Type::array(&type_map(ty.as_ref().clone(), f), len),
+        Type::Array(ty, len) => Type::Array(Box::new(type_map(*ty, f)), len),
         Type::Func(args, rettype, typeparams) => {
             let new_args = types_map(args, f);
-            let new_rettype = type_map(rettype.as_ref().clone(), f);
+            let new_rettype = type_map(*rettype, f);
             let new_typeparams = types_map(typeparams, f);
-            Type::function(&new_args, &new_rettype, &new_typeparams)
+            Type::Func(new_args, Box::new(new_rettype), new_typeparams)
         }
         // Not super sure whether this is necessary, but can't hurt.
         Type::Named(nm, tys) => Type::Named(nm, types_map(tys, f)),

          
@@ 365,8 363,8 @@ fn type_map(typ: Type, f: &mut dyn FnMut
         Type::Enum(_) => typ,
         Type::Generic(_) => typ,
         Type::Uniq(t) => {
-            let new_t = type_map(t.as_ref().clone(), f);
-            Type::Uniq(Arc::new(new_t))
+            let new_t = type_map(*t, f);
+            Type::Uniq(Box::new(new_t))
         }
     };
     f(res)

          
@@ 376,12 374,11 @@ fn type_map(typ: Type, f: &mut dyn FnMut
 fn signature_map(sig: hir::Signature, f: &mut dyn FnMut(Type) -> Type) -> hir::Signature {
     let new_params = sig
         .params
-        .iter()
-        .cloned()
+        .into_iter()
         .map(|(sym, ty)| (sym, type_map(ty, f)))
         .collect();
     hir::Signature {
-        params: Arc::new(new_params),
+        params: new_params,
         rettype: type_map(sig.rettype, f),
         typeparams: types_map(sig.typeparams, f),
     }

          
M src/passes/struct_to_tuple.rs +10 -10
@@ 38,11 38,9 @@ fn tuplize_type(typ: Type) -> Type {
             // on the field names.
 
             // TODO: What do we do with generics?  Anything?
-            let tuple_fields = fields
-                .values()
-                .map(|ty| type_map(ty.clone(), &mut tuplize_type))
+            let tuple_fields = fields.values().map(|ty| type_map(ty.clone(), &mut tuplize_type))
                 .collect();
-            Type::tuple(Arc::new(tuple_fields))
+            Type::tuple(tuple_fields)
         }
         other => other,
     }

          
@@ 79,7 77,10 @@ fn tuplize_expr(expr: ExprNode, tck: &mu
                     .map(|(ky, vl)| (offset_of_field(type_body, ky), vl))
                     .collect();
                 ordered_body.sort_by(|a, b| a.0.cmp(&b.0));
-                let new_body = ordered_body.into_iter().map(|(_i, expr)| expr).collect();
+                let new_body = ordered_body
+                    .into_iter()
+                    .map(|(_i, expr)| expr)
+                    .collect();
 
                 E::TupleCtor { body: new_body }
             }

          
@@ 270,15 271,14 @@ mod tests {
         let mut body = BTreeMap::new();
         body.insert(Sym::new("foo"), Type::i32());
         body.insert(Sym::new("bar"), Type::i64());
-        let body = Arc::new(body);
 
-        let desired = tuplize_type(Type::Struct(body.clone(), Arc::new(vec![])));
-        let inp = Type::Struct(body, Arc::new(vec![]));
+        let desired = tuplize_type(Type::Struct(body.clone(), vec![]));
+        let inp = Type::Struct(body, vec![]);
         let out = type_map(inp.clone(), &mut tuplize_type);
         assert_eq!(out, desired);
 
-        let desired2 = Type::array(&out, 3);
-        let inp2 = Type::array(&inp, 3);
+        let desired2 = Type::Array(Box::new(out), 3);
+        let inp2 = Type::Array(Box::new(inp), 3);
         let out2 = type_map(inp2, &mut tuplize_type);
         assert_eq!(out2, desired2);
     }

          
M src/typeck.rs +17 -20
@@ 409,7 409,7 @@ impl Tck {
         let tinfo = match t {
             Type::Prim(ty) => TypeInfo::Prim(*ty),
             Type::Never => TypeInfo::Never,
-            Type::Enum(vals) => TypeInfo::Enum((&**vals).clone()),
+            Type::Enum(vals) => TypeInfo::Enum(vals.clone()),
             Type::Named(s, args) => {
                 let new_args = args.iter().map(|t| self.insert_known(t)).collect();
                 TypeInfo::Named(*s, new_args)

          
@@ 726,11 726,11 @@ impl Tck {
             Never => Ok(Type::Never),
             Prim(ty) => Ok(Type::Prim(*ty)),
             Ref(id) => self.reconstruct(*id),
-            Enum(ts) => Ok(Type::Enum(Arc::new(ts.clone()))),
+            Enum(ts) => Ok(Type::Enum(ts.clone())),
             Named(s, args) => {
                 let arg_types: Result<Vec<_>, _> =
                     args.iter().map(|x| self.reconstruct(*x)).collect();
-                Ok(Type::Named(*s, Arc::new(arg_types?)))
+                Ok(Type::Named(*s, arg_types?))
             }
             Func(args, rettype, typeparams) => {
                 let real_args: Result<Vec<Type>, TypeError> =

          
@@ 738,12 738,10 @@ impl Tck {
                 let type_param_types: Result<Vec<Type>, _> =
                     typeparams.iter().map(|x| self.reconstruct(*x)).collect();
 
-                let real_args = real_args?;
-                let type_param_types = type_param_types?;
-                Ok(Type::function(
-                    &real_args,
-                    &self.reconstruct(*rettype)?,
-                    &type_param_types,
+                Ok(Type::Func(
+                    real_args?,
+                    Box::new(self.reconstruct(*rettype)?),
+                    type_param_types?,
                 ))
             }
             TypeParam(name) => Ok(Type::Generic(*name)),

          
@@ 757,11 755,11 @@ impl Tck {
                     .collect();
                 // TODO: The empty params here feels suspicious, verify.
                 let params = vec![];
-                Ok(Type::Struct(Arc::new(real_body?), Arc::new(params)))
+                Ok(Type::Struct(real_body?, params))
             }
             Array(ty, len) => {
                 let real_body = self.reconstruct(*ty)?;
-                Ok(Type::array(&real_body, len.unwrap()))
+                Ok(Type::Array(Box::new(real_body), len.unwrap()))
             }
             Sum(body) => {
                 let real_body: Result<BTreeMap<_, _>, TypeError> = body

          
@@ 772,11 770,11 @@ impl Tck {
                     })
                     .collect();
                 let params = vec![];
-                Ok(Type::Sum(Arc::new(real_body?), Arc::new(params)))
+                Ok(Type::Sum(real_body?, params))
             }
             Uniq(ty) => {
                 let inner_type = self.reconstruct(*ty)?;
-                Ok(Type::Uniq(Arc::new(inner_type)))
+                Ok(Type::Uniq(Box::new(inner_type)))
             }
         }
     }

          
@@ 806,7 804,7 @@ impl Tck {
             let typeinfo = match t {
                 Type::Prim(val) => TypeInfo::Prim(*val),
                 Type::Never => TypeInfo::Never,
-                Type::Enum(vals) => TypeInfo::Enum((**vals).clone()),
+                Type::Enum(vals) => TypeInfo::Enum(vals.clone()),
                 Type::Named(s, args) => {
                     let inst_args: Vec<_> =
                         args.iter().map(|t| helper(tck, named_types, t)).collect();

          
@@ 916,7 914,7 @@ impl Drop for ScopeGuard {
 
 impl Symtbl {
     fn add_builtins(&self, tck: &mut Tck) {
-        for builtin in &*builtins::all() {
+        for builtin in &*builtins::BUILTINS {
             let ty = tck.insert_known(&builtin.sig);
             self.add_var(builtin.name, ty, false);
         }

          
@@ 1010,7 1008,7 @@ fn typecheck_func_body(
     */
     // Insert info about the function signature
     let mut params = vec![];
-    for (_paramname, paramtype) in &*signature.params {
+    for (_paramname, paramtype) in &signature.params {
         let p = tck.insert_known(paramtype);
         params.push(p);
     }

          
@@ 1033,7 1031,7 @@ fn typecheck_func_body(
 
     // Add params to function's scope
     let _guard = symtbl.push_scope();
-    for (paramname, paramtype) in &*signature.params {
+    for (paramname, paramtype) in &signature.params {
         let p = tck.insert_known(paramtype);
         symtbl.add_var(*paramname, p, false);
     }

          
@@ 1474,8 1472,7 @@ fn typecheck_expr(
             tck.unify(symtbl, tid, body_type)?;
             trace!("Done unifying type ctor");
             // The type the expression returns
-            let constructed_type =
-                tck.insert_known(&Type::Named(*name, Arc::new(type_params.clone())));
+            let constructed_type = tck.insert_known(&Type::Named(*name, type_params.clone()));
             tck.set_expr_type(expr, constructed_type);
             Ok(constructed_type)
         }

          
@@ 1626,7 1623,7 @@ fn predeclare_decls(tck: &mut Tck, symtb
             } => {
                 // TODO: Kinda duplicated, not a huge fan.
                 let mut params = vec![];
-                for (_paramname, paramtype) in &*signature.params {
+                for (_paramname, paramtype) in &signature.params {
                     let p = tck.insert_known(paramtype);
                     params.push(p);
                 }