about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-09-07 07:37:19 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-09-07 07:54:11 -0700
commitfb8786fe522ed96172cf1ae8e205e3f2722e834c (patch)
tree7021370b9bb017b64ba4e9780f0570cd563db244 /src/rustc
parent699505899ece6339a892f252efb085fe301776b6 (diff)
downloadrust-fb8786fe522ed96172cf1ae8e205e3f2722e834c.tar.gz
rust-fb8786fe522ed96172cf1ae8e205e3f2722e834c.zip
Refactor fn_ty, working towards #3320
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/decoder.rs2
-rw-r--r--src/rustc/metadata/encoder.rs2
-rw-r--r--src/rustc/metadata/tydecode.rs15
-rw-r--r--src/rustc/metadata/tyencode.rs14
-rw-r--r--src/rustc/middle/borrowck/check_loans.rs4
-rw-r--r--src/rustc/middle/lint.rs2
-rw-r--r--src/rustc/middle/trans/base.rs6
-rw-r--r--src/rustc/middle/trans/closure.rs20
-rw-r--r--src/rustc/middle/trans/expr.rs13
-rw-r--r--src/rustc/middle/trans/foreign.rs40
-rw-r--r--src/rustc/middle/trans/monomorphize.rs52
-rw-r--r--src/rustc/middle/trans/reflect.rs18
-rw-r--r--src/rustc/middle/trans/shape.rs285
-rw-r--r--src/rustc/middle/trans/type_use.rs4
-rw-r--r--src/rustc/middle/tstate/auxiliary.rs16
-rw-r--r--src/rustc/middle/ty.rs326
-rw-r--r--src/rustc/middle/typeck.rs62
-rw-r--r--src/rustc/middle/typeck/astconv.rs13
-rw-r--r--src/rustc/middle/typeck/check.rs96
-rw-r--r--src/rustc/middle/typeck/check/method.rs18
-rw-r--r--src/rustc/middle/typeck/check/regionck.rs11
-rw-r--r--src/rustc/middle/typeck/check/regionmanip.rs4
-rw-r--r--src/rustc/middle/typeck/collect.rs55
-rw-r--r--src/rustc/middle/typeck/infer.rs24
-rw-r--r--src/rustc/middle/typeck/infer/combine.rs57
-rw-r--r--src/rustc/middle/typeck/infer/glb.rs10
-rw-r--r--src/rustc/middle/typeck/infer/lattice.rs4
-rw-r--r--src/rustc/middle/typeck/infer/lub.rs10
-rw-r--r--src/rustc/middle/typeck/infer/region_var_bindings.rs38
-rw-r--r--src/rustc/middle/typeck/infer/resolve.rs10
-rw-r--r--src/rustc/middle/typeck/infer/sub.rs10
-rw-r--r--src/rustc/middle/typeck/infer/unify.rs16
-rw-r--r--src/rustc/util/ppaux.rs11
33 files changed, 699 insertions, 569 deletions
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 4e2c7b8ee72..b738295d262 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -585,7 +585,7 @@ fn get_enum_variants(intr: ident_interner, cdata: cmd, id: ast::node_id,
         let mut arg_tys: ~[ty::t] = ~[];
         match ty::get(ctor_ty).struct {
           ty::ty_fn(f) => {
-            for f.inputs.each |a| { vec::push(arg_tys, a.ty); }
+            for f.sig.inputs.each |a| { vec::push(arg_tys, a.ty); }
           }
           _ => { /* Nullary enum variant. */ }
         }
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index b1b5e081a80..803c9967d0c 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -750,7 +750,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item,
                 encode_name(ecx, ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
                 encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
+                encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
                 encode_self_type(ebml_w, mty.self_ty);
                 ebml_w.end_tag();
               }
diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs
index 24f706eeb46..8fe58a93824 100644
--- a/src/rustc/metadata/tydecode.rs
+++ b/src/rustc/metadata/tydecode.rs
@@ -9,6 +9,7 @@ use syntax::ast_util;
 use syntax::ast_util::respan;
 use middle::ty;
 use std::map::hashmap;
+use ty::{FnTyBase, FnMeta, FnSig};
 
 export parse_ty_data, parse_def_id, parse_ident;
 export parse_bounds_data;
@@ -274,7 +275,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         parse_ty_rust_fn(st, conv)
       }
       'X' => {
-        return ty::mk_var(st.tcx, ty::ty_vid(parse_int(st) as uint));
+        return ty::mk_var(st.tcx, ty::TyVid(parse_int(st) as uint));
       }
       'Y' => return ty::mk_type(st.tcx),
       'C' => {
@@ -372,7 +373,7 @@ fn parse_purity(c: char) -> purity {
     }
 }
 
-fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
+fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
     let proto = parse_proto(st);
     let purity = parse_purity(next(st));
     let bounds = parse_bounds(st, conv);
@@ -392,8 +393,14 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
     }
     st.pos += 1u; // eat the ']'
     let (ret_style, ret_ty) = parse_ret_ty(st, conv);
-    return {purity: purity, proto: proto, bounds: bounds, inputs: inputs,
-            output: ret_ty, ret_style: ret_style};
+    return FnTyBase {
+        meta: FnMeta {purity: purity,
+                      proto: proto,
+                      bounds: bounds,
+                      ret_style: ret_style},
+        sig: FnSig {inputs: inputs,
+                    output: ret_ty}
+    };
 }
 
 
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 0ecb9dc3dc0..622ba1a5cce 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -342,19 +342,19 @@ fn enc_purity(w: io::Writer, p: purity) {
     }
 }
 
-fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::fn_ty) {
-    enc_proto(w, cx, ft.proto);
-    enc_purity(w, ft.purity);
-    enc_bounds(w, cx, ft.bounds);
+fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) {
+    enc_proto(w, cx, ft.meta.proto);
+    enc_purity(w, ft.meta.purity);
+    enc_bounds(w, cx, ft.meta.bounds);
     w.write_char('[');
-    for ft.inputs.each |arg| {
+    for ft.sig.inputs.each |arg| {
         enc_mode(w, cx, arg.mode);
         enc_ty(w, cx, arg.ty);
     }
     w.write_char(']');
-    match ft.ret_style {
+    match ft.meta.ret_style {
       noreturn => w.write_char('!'),
-      _ => enc_ty(w, cx, ft.output)
+      _ => enc_ty(w, cx, ft.sig.output)
     }
 }
 
diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs
index 7f2964181d8..a81620b20ba 100644
--- a/src/rustc/middle/borrowck/check_loans.rs
+++ b/src/rustc/middle/borrowck/check_loans.rs
@@ -218,13 +218,13 @@ impl check_loan_ctxt {
         let callee_ty = ty::node_id_to_type(tcx, callee_id);
         match ty::get(callee_ty).struct {
           ty::ty_fn(fn_ty) => {
-            match fn_ty.purity {
+            match fn_ty.meta.purity {
               ast::pure_fn => return, // case (c) above
               ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
                 self.report_purity_error(
                     pc, callee_span,
                     fmt!("access to %s function",
-                         pprust::purity_to_str(fn_ty.purity)));
+                         pprust::purity_to_str(fn_ty.meta.purity)));
               }
             }
           }
diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs
index e38ba74fecf..8c2776d3ceb 100644
--- a/src/rustc/middle/lint.rs
+++ b/src/rustc/middle/lint.rs
@@ -659,7 +659,7 @@ fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl,
     match ty::get(fn_ty).struct {
       ty::ty_fn(fn_ty) => {
         let mut counter = 0;
-        do vec::iter2(fn_ty.inputs, decl.inputs) |arg_ty, arg_ast| {
+        do vec::iter2(fn_ty.sig.inputs, decl.inputs) |arg_ty, arg_ast| {
             counter += 1;
             debug!("arg %d, ty=%s, mode=%s",
                    counter,
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 3eef274e9d6..acf51691a96 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -529,10 +529,10 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
         let ccx = cx.ccx();
         let mut cx = cx;
         match ty::get(fn_ty).struct {
-          ty::ty_fn({inputs: args, _}) => {
+          ty::ty_fn(ref fn_ty) => {
             let mut j = 0u;
             let v_id = variant.id;
-            for vec::each(args) |a| {
+            for vec::each(fn_ty.sig.inputs) |a| {
                 let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j);
                 let ty_subst = ty::subst_tps(ccx.tcx, tps, a.ty);
                 cx = f(cx, llfldp_a, ty_subst);
@@ -1984,7 +1984,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
     let main_takes_argv =
         // invariant!
         match ty::get(main_node_type).struct {
-          ty::ty_fn({inputs, _}) => inputs.len() != 0u,
+          ty::ty_fn(ref fn_ty) => fn_ty.sig.inputs.len() != 0u,
           _ => ccx.sess.span_fatal(sp, ~"main has a non-function type")
         };
 
diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs
index 9cf4393346b..57fcf66c701 100644
--- a/src/rustc/middle/trans/closure.rs
+++ b/src/rustc/middle/trans/closure.rs
@@ -425,17 +425,15 @@ fn make_fn_glue(
         }
     };
 
-    return match ty::get(t).struct {
-      ty::ty_fn({proto: ty::proto_bare, _}) |
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) =>
-        bcx,
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) =>
-        fn_env(ty::ck_uniq),
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) =>
-        fn_env(ty::ck_box),
-      _ =>
-        fail ~"make_fn_glue invoked on non-function type"
-    };
+    let proto = ty::ty_fn_proto(t);
+    match proto {
+        ty::proto_bare | ty::proto_vstore(ty::vstore_slice(_)) => bcx,
+        ty::proto_vstore(ty::vstore_uniq) => fn_env(ty::ck_uniq),
+        ty::proto_vstore(ty::vstore_box) => fn_env(ty::ck_box),
+        ty::proto_vstore(ty::vstore_fixed(_)) => {
+            cx.sess().bug(~"Closure with fixed vstore");
+        }
+    }
 }
 
 fn make_opaque_cbox_take_glue(
diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs
index 1e9c36b1e7e..118eff8c53b 100644
--- a/src/rustc/middle/trans/expr.rs
+++ b/src/rustc/middle/trans/expr.rs
@@ -447,13 +447,14 @@ fn trans_rvalue_dps(bcx: block, expr: @ast::expr, dest: Dest) -> block {
         ast::expr_fn_block(decl, body, cap_clause) => {
             let expr_ty = expr_ty(bcx, expr);
             match ty::get(expr_ty).struct {
-                ty::ty_fn({proto, _}) => {
+                ty::ty_fn(ref fn_ty) => {
                     debug!("translating fn_block %s with type %s",
                            expr_to_str(expr, tcx.sess.intr()),
                            ty_to_str(tcx, expr_ty));
-                    return closure::trans_expr_fn(bcx, proto, decl, body,
-                                                  expr.id, cap_clause, None,
-                                                  dest);
+                    return closure::trans_expr_fn(
+                        bcx, fn_ty.meta.proto, decl, body,
+                        expr.id, cap_clause, None,
+                        dest);
                 }
                 _ => {
                     bcx.sess().impossible_case(
@@ -463,11 +464,11 @@ fn trans_rvalue_dps(bcx: block, expr: @ast::expr, dest: Dest) -> block {
         }
         ast::expr_loop_body(blk) => {
             match ty::get(expr_ty(bcx, expr)).struct {
-                ty::ty_fn({proto, _}) => {
+                ty::ty_fn(ref fn_ty) => {
                     match blk.node {
                         ast::expr_fn_block(decl, body, cap) => {
                             return closure::trans_expr_fn(
-                                bcx, proto, decl, body, blk.id,
+                                bcx, fn_ty.meta.proto, decl, body, blk.id,
                                 cap, Some(None), dest);
                         }
                         _ => {
diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs
index cd2be095178..bb5ea98e1b4 100644
--- a/src/rustc/middle/trans/foreign.rs
+++ b/src/rustc/middle/trans/foreign.rs
@@ -20,6 +20,7 @@ use util::ppaux::ty_to_str;
 use datum::*;
 use callee::*;
 use expr::{Dest, Ignore};
+use ty::{FnTyBase, FnMeta, FnSig};
 
 export link_name, trans_foreign_mod, register_foreign_fn, trans_foreign_fn,
        trans_intrinsic;
@@ -439,12 +440,12 @@ type c_stack_tys = {
 fn c_arg_and_ret_lltys(ccx: @crate_ctxt,
                        id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) {
     match ty::get(ty::node_id_to_type(ccx.tcx, id)).struct {
-      ty::ty_fn({inputs: arg_tys, output: ret_ty, _}) => {
-        let llargtys = type_of_explicit_args(ccx, arg_tys);
-        let llretty = type_of::type_of(ccx, ret_ty);
-        (llargtys, llretty, ret_ty)
-      }
-      _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type")
+        ty::ty_fn(ref fn_ty) => {
+            let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs);
+            let llretty = type_of::type_of(ccx, fn_ty.sig.output);
+            (llargtys, llretty, fn_ty.sig.output)
+        }
+        _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type")
     }
 }
 
@@ -953,20 +954,19 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
         ~"frame_address" => {
             let frameaddress = ccx.intrinsics.get(~"llvm.frameaddress");
             let frameaddress_val = Call(bcx, frameaddress, ~[C_i32(0i32)]);
-            let fty = ty::mk_fn(bcx.tcx(), {
-                purity: ast::impure_fn,
-                proto:
-                    ty::proto_vstore(ty::vstore_slice(
-                        ty::re_bound(ty::br_anon(0)))),
-                bounds: @~[],
-                inputs: ~[{
-                    mode: ast::expl(ast::by_val),
-                    ty: ty::mk_imm_ptr(
-                        bcx.tcx(),
-                        ty::mk_mach_uint(bcx.tcx(), ast::ty_u8))
-                }],
-                output: ty::mk_nil(bcx.tcx()),
-                ret_style: ast::return_val
+            let star_u8 = ty::mk_imm_ptr(
+                bcx.tcx(),
+                ty::mk_mach_uint(bcx.tcx(), ast::ty_u8));
+            let fty = ty::mk_fn(bcx.tcx(), FnTyBase {
+                meta: FnMeta {purity: ast::impure_fn,
+                              proto:
+                                  ty::proto_vstore(ty::vstore_slice(
+                                      ty::re_bound(ty::br_anon(0)))),
+                              bounds: @~[],
+                              ret_style: ast::return_val},
+                sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
+                                       ty: star_u8}],
+                            output: ty::mk_nil(bcx.tcx())}
             });
             let datum = Datum {val: get_param(decl, first_real_arg),
                                mode: ByRef, ty: fty, source: FromLvalue};
diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs
index 962aed37ff1..a0df372173d 100644
--- a/src/rustc/middle/trans/monomorphize.rs
+++ b/src/rustc/middle/trans/monomorphize.rs
@@ -10,6 +10,7 @@ use base::{trans_item, get_item_val, no_self, self_arg, trans_fn,
 use syntax::parse::token::special_idents;
 use type_of::type_of_fn_from_ty;
 use back::link::mangle_exported_name;
+use middle::ty::{FnTyBase, FnMeta, FnSig};
 
 fn monomorphic_fn(ccx: @crate_ctxt,
                   fn_id: ast::def_id,
@@ -198,27 +199,36 @@ fn monomorphic_fn(ccx: @crate_ctxt,
 fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> {
     // FIXME[mono] could do this recursively. is that worthwhile? (#2529)
     match ty::get(ty).struct {
-      ty::ty_box(*) => {
-        Some(ty::mk_opaque_box(tcx))
-      }
-      ty::ty_fn(ref fty) => {
-        Some(ty::mk_fn(tcx, {purity: ast::impure_fn,
-                             proto: fty.proto,
-                             bounds: @~[],
-                             inputs: ~[],
-                             output: ty::mk_nil(tcx),
-                             ret_style: ast::return_val}))
-      }
-      ty::ty_trait(_, _, _) => {
-        Some(ty::mk_fn(tcx, {purity: ast::impure_fn,
-                             proto: ty::proto_vstore(ty::vstore_box),
-                             bounds: @~[],
-                             inputs: ~[],
-                             output: ty::mk_nil(tcx),
-                             ret_style: ast::return_val}))
-      }
-      ty::ty_ptr(_) => Some(ty::mk_uint(tcx)),
-      _ => None
+        ty::ty_box(*) => {
+            Some(ty::mk_opaque_box(tcx))
+        }
+        ty::ty_fn(ref fty) => {
+            Some(ty::mk_fn(
+                tcx,
+                FnTyBase {meta: FnMeta {purity: ast::impure_fn,
+                                        proto: fty.meta.proto,
+                                        bounds: @~[],
+                                        ret_style: ast::return_val},
+                          sig: FnSig {inputs: ~[],
+                                      output: ty::mk_nil(tcx)}}))
+        }
+        ty::ty_trait(_, _, _) => {
+            let box_proto = ty::proto_vstore(ty::vstore_box);
+            Some(ty::mk_fn(
+                tcx,
+                FnTyBase {meta: FnMeta {purity: ast::impure_fn,
+                                        proto: box_proto,
+                                        bounds: @~[],
+                                        ret_style: ast::return_val},
+                          sig: FnSig {inputs: ~[],
+                                      output: ty::mk_nil(tcx)}}))
+        }
+        ty::ty_ptr(_) => {
+            Some(ty::mk_uint(tcx))
+        }
+        _ => {
+            None
+        }
     }
 }
 
diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs
index 5aeddac8ab3..c78e264a86f 100644
--- a/src/rustc/middle/trans/reflect.rs
+++ b/src/rustc/middle/trans/reflect.rs
@@ -178,14 +178,14 @@ impl reflector {
 
           // FIXME (#2594): fetch constants out of intrinsic:: for the
           // numbers.
-          ty::ty_fn(fty) => {
-            let pureval = match fty.purity {
+          ty::ty_fn(ref fty) => {
+            let pureval = match fty.meta.purity {
               ast::pure_fn => 0u,
               ast::unsafe_fn => 1u,
               ast::impure_fn => 2u,
               ast::extern_fn => 3u
             };
-            let protoval = match fty.proto {
+            let protoval = match fty.meta.proto {
               ty::proto_bare => 0u,
               ty::proto_vstore(ty::vstore_uniq) => 2u,
               ty::proto_vstore(ty::vstore_box) => 3u,
@@ -193,16 +193,16 @@ impl reflector {
               ty::proto_vstore(ty::vstore_fixed(_)) =>
                 fail ~"fixed unexpected"
             };
-            let retval = match fty.ret_style {
+            let retval = match fty.meta.ret_style {
               ast::noreturn => 0u,
               ast::return_val => 1u
             };
             let extra = ~[self.c_uint(pureval),
-                         self.c_uint(protoval),
-                         self.c_uint(vec::len(fty.inputs)),
-                         self.c_uint(retval)];
+                          self.c_uint(protoval),
+                          self.c_uint(vec::len(fty.sig.inputs)),
+                          self.c_uint(retval)];
             self.visit(~"enter_fn", extra);
-            for fty.inputs.eachi |i, arg| {
+            for fty.sig.inputs.eachi |i, arg| {
                 let modeval = match arg.mode {
                   ast::infer(_) => 0u,
                   ast::expl(e) => match e {
@@ -220,7 +220,7 @@ impl reflector {
             }
             self.visit(~"fn_output",
                        ~[self.c_uint(retval),
-                         self.c_tydesc(fty.output)]);
+                         self.c_tydesc(fty.sig.output)]);
             self.visit(~"leave_fn", extra);
           }
 
diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs
index 92ee4e5dc90..f93d9c0b593 100644
--- a/src/rustc/middle/trans/shape.rs
+++ b/src/rustc/middle/trans/shape.rs
@@ -213,158 +213,161 @@ fn add_substr(&dest: ~[u8], src: ~[u8]) {
 
 fn shape_of(ccx: @crate_ctxt, t: ty::t) -> ~[u8] {
     match ty::get(t).struct {
-      ty::ty_nil | ty::ty_bool | ty::ty_uint(ast::ty_u8) |
-      ty::ty_bot => ~[shape_u8],
-      ty::ty_int(ast::ty_i) => ~[s_int(ccx.tcx)],
-      ty::ty_float(ast::ty_f) => ~[s_float(ccx.tcx)],
-      ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) => ~[s_uint(ccx.tcx)],
-      ty::ty_type => ~[s_tydesc(ccx.tcx)],
-      ty::ty_int(ast::ty_i8) => ~[shape_i8],
-      ty::ty_uint(ast::ty_u16) => ~[shape_u16],
-      ty::ty_int(ast::ty_i16) => ~[shape_i16],
-      ty::ty_uint(ast::ty_u32) => ~[shape_u32],
-      ty::ty_int(ast::ty_i32) | ty::ty_int(ast::ty_char) => ~[shape_i32],
-      ty::ty_uint(ast::ty_u64) => ~[shape_u64],
-      ty::ty_int(ast::ty_i64) => ~[shape_i64],
-      ty::ty_float(ast::ty_f32) => ~[shape_f32],
-      ty::ty_float(ast::ty_f64) => ~[shape_f64],
-      ty::ty_estr(ty::vstore_uniq) => {
-        shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
-      }
-      ty::ty_enum(did, substs) => {
-        match enum_kind(ccx, did) {
-          tk_unit => ~[s_variant_enum_t(ccx.tcx)],
-          tk_enum => ~[s_variant_enum_t(ccx.tcx)],
-          tk_newtype | tk_complex => {
-            let mut s = ~[shape_enum], id;
-            let nom_id = mk_nominal_id(ccx.tcx, did, None, substs.tps);
-            match ccx.shape_cx.tag_id_to_index.find(nom_id) {
-              None => {
-                id = ccx.shape_cx.next_tag_id;
-                ccx.shape_cx.tag_id_to_index.insert(nom_id, id);
-                ccx.shape_cx.tag_order.push({did: did, substs: substs});
-                ccx.shape_cx.next_tag_id += 1u16;
-              }
-              Some(existing_id) => id = existing_id,
-            }
-            add_u16(s, id as u16);
+        ty::ty_nil | ty::ty_bool | ty::ty_uint(ast::ty_u8) |
+        ty::ty_bot => ~[shape_u8],
+        ty::ty_int(ast::ty_i) => ~[s_int(ccx.tcx)],
+        ty::ty_float(ast::ty_f) => ~[s_float(ccx.tcx)],
+        ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) => ~[s_uint(ccx.tcx)],
+        ty::ty_type => ~[s_tydesc(ccx.tcx)],
+        ty::ty_int(ast::ty_i8) => ~[shape_i8],
+        ty::ty_uint(ast::ty_u16) => ~[shape_u16],
+        ty::ty_int(ast::ty_i16) => ~[shape_i16],
+        ty::ty_uint(ast::ty_u32) => ~[shape_u32],
+        ty::ty_int(ast::ty_i32) | ty::ty_int(ast::ty_char) => ~[shape_i32],
+        ty::ty_uint(ast::ty_u64) => ~[shape_u64],
+        ty::ty_int(ast::ty_i64) => ~[shape_i64],
+        ty::ty_float(ast::ty_f32) => ~[shape_f32],
+        ty::ty_float(ast::ty_f64) => ~[shape_f64],
+        ty::ty_estr(ty::vstore_uniq) => {
+            shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
+        }
+        ty::ty_enum(did, substs) => {
+            match enum_kind(ccx, did) {
+                tk_unit => ~[s_variant_enum_t(ccx.tcx)],
+                tk_enum => ~[s_variant_enum_t(ccx.tcx)],
+                tk_newtype | tk_complex => {
+                    let mut s = ~[shape_enum], id;
+                    let nom_id = mk_nominal_id(ccx.tcx, did,
+                                               None, substs.tps);
+                    match ccx.shape_cx.tag_id_to_index.find(nom_id) {
+                        None => {
+                            id = ccx.shape_cx.next_tag_id;
+                            ccx.shape_cx.tag_id_to_index.insert(nom_id, id);
+                            ccx.shape_cx.tag_order.push({did: did,
+                                                         substs: substs});
+                            ccx.shape_cx.next_tag_id += 1u16;
+                        }
+                        Some(existing_id) => id = existing_id,
+                    }
+                    add_u16(s, id as u16);
 
+                    s
+                }
+            }
+        }
+        ty::ty_estr(ty::vstore_box) |
+        ty::ty_evec(_, ty::vstore_box) |
+        ty::ty_box(_) | ty::ty_opaque_box => ~[shape_box],
+        ty::ty_uniq(mt) => {
+            let mut s = ~[shape_uniq];
+            add_substr(s, shape_of(ccx, mt.ty));
             s
-          }
         }
-      }
-      ty::ty_estr(ty::vstore_box) |
-      ty::ty_evec(_, ty::vstore_box) |
-      ty::ty_box(_) | ty::ty_opaque_box => ~[shape_box],
-      ty::ty_uniq(mt) => {
-        let mut s = ~[shape_uniq];
-        add_substr(s, shape_of(ccx, mt.ty));
-        s
-      }
-      ty::ty_unboxed_vec(mt) => {
-        let mut s = ~[shape_unboxed_vec];
-        add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
-        add_substr(s, shape_of(ccx, mt.ty));
-        s
-      }
-      ty::ty_evec(_, ty::vstore_uniq) => {
-        shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
-      }
+        ty::ty_unboxed_vec(mt) => {
+            let mut s = ~[shape_unboxed_vec];
+            add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
+            add_substr(s, shape_of(ccx, mt.ty));
+            s
+        }
+        ty::ty_evec(_, ty::vstore_uniq) => {
+            shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
+        }
 
-      ty::ty_estr(ty::vstore_fixed(n)) => {
-        let mut s = ~[shape_fixedvec];
-        let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
-        assert (n + 1u) <= 0xffffu;
-        add_u16(s, (n + 1u) as u16);
-        add_bool(s, true);
-        add_substr(s, shape_of(ccx, u8_t));
-        s
-      }
+        ty::ty_estr(ty::vstore_fixed(n)) => {
+            let mut s = ~[shape_fixedvec];
+            let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
+            assert (n + 1u) <= 0xffffu;
+            add_u16(s, (n + 1u) as u16);
+            add_bool(s, true);
+            add_substr(s, shape_of(ccx, u8_t));
+            s
+        }
 
-      ty::ty_evec(mt, ty::vstore_fixed(n)) => {
-        let mut s = ~[shape_fixedvec];
-        assert n <= 0xffffu;
-        add_u16(s, n as u16);
-        add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
-        add_substr(s, shape_of(ccx, mt.ty));
-        s
-      }
+        ty::ty_evec(mt, ty::vstore_fixed(n)) => {
+            let mut s = ~[shape_fixedvec];
+            assert n <= 0xffffu;
+            add_u16(s, n as u16);
+            add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
+            add_substr(s, shape_of(ccx, mt.ty));
+            s
+        }
 
-      ty::ty_estr(ty::vstore_slice(_)) => {
-        let mut s = ~[shape_slice];
-        let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
-        add_bool(s, true); // is_pod
-        add_bool(s, true); // is_str
-        add_substr(s, shape_of(ccx, u8_t));
-        s
-      }
+        ty::ty_estr(ty::vstore_slice(_)) => {
+            let mut s = ~[shape_slice];
+            let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
+            add_bool(s, true); // is_pod
+            add_bool(s, true); // is_str
+            add_substr(s, shape_of(ccx, u8_t));
+            s
+        }
 
-      ty::ty_evec(mt, ty::vstore_slice(_)) => {
-        let mut s = ~[shape_slice];
-        add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
-        add_bool(s, false); // is_str
-        add_substr(s, shape_of(ccx, mt.ty));
-        s
-      }
+        ty::ty_evec(mt, ty::vstore_slice(_)) => {
+            let mut s = ~[shape_slice];
+            add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
+            add_bool(s, false); // is_str
+            add_substr(s, shape_of(ccx, mt.ty));
+            s
+        }
 
-      ty::ty_rec(fields) => {
-        let mut s = ~[shape_struct], sub = ~[];
-        for vec::each(fields) |f| {
-            sub += shape_of(ccx, f.mt.ty);
+        ty::ty_rec(fields) => {
+            let mut s = ~[shape_struct], sub = ~[];
+            for vec::each(fields) |f| {
+                sub += shape_of(ccx, f.mt.ty);
+            }
+            add_substr(s, sub);
+            s
         }
-        add_substr(s, sub);
-        s
-      }
-      ty::ty_tup(elts) => {
-        let mut s = ~[shape_struct], sub = ~[];
-        for vec::each(elts) |elt| {
-            sub += shape_of(ccx, elt);
+        ty::ty_tup(elts) => {
+            let mut s = ~[shape_struct], sub = ~[];
+            for vec::each(elts) |elt| {
+                sub += shape_of(ccx, elt);
+            }
+            add_substr(s, sub);
+            s
         }
-        add_substr(s, sub);
-        s
-      }
-      ty::ty_trait(_, _, _) => ~[shape_box_fn],
-      ty::ty_class(did, ref substs) => {
-        // same as records, unless there's a dtor
-        let tps = substs.tps;
-        let m_dtor_did = ty::ty_dtor(ccx.tcx, did);
-        let mut s = if option::is_some(m_dtor_did) {
-            ~[shape_res]
-          }
-        else { ~[shape_struct] }, sub = ~[];
-        do option::iter(m_dtor_did) |dtor_did| {
-          let ri = @{did: dtor_did, parent_id: Some(did), tps: tps};
-          let id = ccx.shape_cx.resources.intern(ri);
-          add_u16(s, id as u16);
-        };
-        for ty::class_items_as_mutable_fields(ccx.tcx, did, substs).each |f| {
-           sub += shape_of(ccx, f.mt.ty);
+        ty::ty_trait(_, _, _) => ~[shape_box_fn],
+        ty::ty_class(did, ref substs) => {
+            // same as records, unless there's a dtor
+            let tps = substs.tps;
+            let m_dtor_did = ty::ty_dtor(ccx.tcx, did);
+            let mut s = if option::is_some(m_dtor_did) {
+                ~[shape_res]
+            }
+            else { ~[shape_struct] }, sub = ~[];
+            do option::iter(m_dtor_did) |dtor_did| {
+                let ri = @{did: dtor_did, parent_id: Some(did), tps: tps};
+                let id = ccx.shape_cx.resources.intern(ri);
+                add_u16(s, id as u16);
+            };
+            for ty::class_items_as_mutable_fields(ccx.tcx, did,
+                                                  substs).each |f| {
+                sub += shape_of(ccx, f.mt.ty);
+            }
+            add_substr(s, sub);
+            s
+        }
+        ty::ty_rptr(_, mt) => {
+            let mut s = ~[shape_rptr];
+            add_substr(s, shape_of(ccx, mt.ty));
+            s
+        }
+        ty::ty_param(*) => {
+            ccx.tcx.sess.bug(~"non-monomorphized type parameter");
+        }
+        ty::ty_fn(ref fn_ty) => {
+            match fn_ty.meta.proto {
+                ty::proto_vstore(ty::vstore_box) => ~[shape_box_fn],
+                ty::proto_vstore(ty::vstore_uniq) => ~[shape_uniq_fn],
+                ty::proto_vstore(ty::vstore_slice(_)) => ~[shape_stack_fn],
+                ty::proto_bare => ~[shape_bare_fn],
+                ty::proto_vstore(ty::vstore_fixed(_)) =>
+                fail ~"fixed vstore is impossible",
+            }
+        }
+        ty::ty_opaque_closure_ptr(_) => ~[shape_opaque_closure_ptr],
+        ty::ty_infer(_) | ty::ty_self => {
+            ccx.sess.bug(~"shape_of: unexpected type struct found")
         }
-        add_substr(s, sub);
-        s
-      }
-      ty::ty_rptr(_, mt) => {
-        let mut s = ~[shape_rptr];
-        add_substr(s, shape_of(ccx, mt.ty));
-        s
-      }
-      ty::ty_param(*) => {
-        ccx.tcx.sess.bug(~"non-monomorphized type parameter");
-      }
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) =>
-        ~[shape_box_fn],
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) =>
-        ~[shape_uniq_fn],
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) =>
-        ~[shape_stack_fn],
-      ty::ty_fn({proto: ty::proto_vstore(ty::vstore_fixed(_)), _}) =>
-        fail ~"fixed vstore is impossible",
-      ty::ty_fn({proto: ty::proto_bare, _}) =>
-        ~[shape_bare_fn],
-      ty::ty_opaque_closure_ptr(_) =>
-        ~[shape_opaque_closure_ptr],
-      ty::ty_infer(_) | ty::ty_self =>
-        ccx.sess.bug(~"shape_of: unexpected type struct found")
     }
 }
 
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index 8048a34c219..4c6b936172f 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -46,8 +46,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
 
     let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))};
     match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct {
-      ty::ty_fn({inputs, _}) => {
-        for vec::each(inputs) |arg| {
+      ty::ty_fn(ref fn_ty) => {
+        for vec::each(fn_ty.sig.inputs) |arg| {
             if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); }
         }
       }
diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs
index 849d4416692..f612ed40a9c 100644
--- a/src/rustc/middle/tstate/auxiliary.rs
+++ b/src/rustc/middle/tstate/auxiliary.rs
@@ -946,16 +946,14 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> ~[mode] {
     let ty = ty::type_autoderef(fcx.ccx.tcx,
                                 ty::node_id_to_type(fcx.ccx.tcx, callee));
     match ty::get(ty).struct {
-      ty::ty_fn({inputs: args, _}) {
-        let mut modes = ~[];
-        for args.each |arg| { vec::push(modes, arg.mode); }
-        return modes;
-      }
-      _ {
-        // Shouldn't happen; callee should be ty_fn.
-        fcx.ccx.tcx.sess.bug(~"non-fn callee type in callee_modes: " +
+        ty::ty_fn(ref fn_ty) {
+            return fn_ty.sig.inputs.map(|input| input.mode);
+        }
+        _ {
+            // Shouldn't happen; callee should be ty_fn.
+            fcx.ccx.tcx.sess.bug(~"non-fn callee type in callee_modes: " +
                                  util::ppaux::ty_to_str(fcx.ccx.tcx, ty));
-      }
+        }
     }
 }
 
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 2f352efc864..f95997c93e9 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -21,7 +21,7 @@ use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
 use std::serialization::{serialize_Option,
                             deserialize_Option};
 
-export ty_vid, int_vid, region_vid, vid;
+export TyVid, IntVid, FnVid, RegionVid, vid;
 export br_hashmap;
 export is_instantiable;
 export node_id_to_type;
@@ -80,7 +80,7 @@ export ty_box, mk_box, mk_imm_box, type_is_box, type_is_boxed;
 export ty_opaque_closure_ptr, mk_opaque_closure_ptr;
 export ty_opaque_box, mk_opaque_box;
 export ty_float, mk_float, mk_mach_float, type_is_fp;
-export ty_fn, fn_ty, mk_fn;
+export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
 export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
 export ty_int, mk_int, mk_mach_int, mk_char;
 export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
@@ -119,7 +119,7 @@ export kind_noncopyable, kind_const;
 export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
 export kind_is_safe_for_default_mode;
 export kind_is_owned;
-export proto_kind, kind_lteq, type_kind;
+export meta_kind, kind_lteq, type_kind;
 export operators;
 export type_err, terr_vstore_kind;
 export type_err_to_str, note_and_explain_type_err;
@@ -203,7 +203,7 @@ type param_bounds = @~[param_bound];
 
 type method = {ident: ast::ident,
                tps: @~[param_bounds],
-               fty: fn_ty,
+               fty: FnTy,
                self_ty: ast::self_ty_,
                vis: ast::visibility};
 
@@ -392,20 +392,42 @@ impl fn_proto : cmp::Eq {
     }
 }
 
-/// Innards of a function type:
-///
-/// - `purity` is the function's effect (pure, impure, unsafe).
-/// - `proto` is the protocol (fn@, fn~, etc).
-/// - `bound` is the parameter bounds on the function's upvars.
-/// - `inputs` is the list of arguments and their modes.
-/// - `output` is the return type.
-/// - `ret_style` indicates whether the function returns a value or fails.
-type fn_ty = {purity: ast::purity,
-              proto: fn_proto,
-              bounds: @~[param_bound],
-              inputs: ~[arg],
-              output: t,
-              ret_style: ret_style};
+/**
+ * Meta information about a closure.
+ *
+ * - `purity` is the function's effect (pure, impure, unsafe).
+ * - `proto` is the protocol (fn@, fn~, etc).
+ * - `bounds` is the parameter bounds on the function's upvars.
+ * - `ret_style` indicates whether the function returns a value or fails. */
+struct FnMeta {
+    purity: ast::purity;
+    proto: fn_proto;
+    bounds: @~[param_bound];
+    ret_style: ret_style;
+}
+
+/**
+ * Signature of a function type, which I have arbitrarily
+ * decided to use to refer to the input/output types.
+ *
+ * - `inputs` is the list of arguments and their modes.
+ * - `output` is the return type. */
+struct FnSig {
+    inputs: ~[arg];
+    output: t;
+}
+
+/**
+ * Function type: combines the meta information and the
+ * type signature.  This particular type is parameterized
+ * by the meta information because, in some cases, the
+ * meta information is inferred. */
+struct FnTyBase<M: cmp::Eq> {
+    meta: M;
+    sig: FnSig;
+}
+
+type FnTy = FnTyBase<FnMeta>;
 
 type param_ty = {idx: uint, def_id: def_id};
 
@@ -440,7 +462,7 @@ enum region {
     re_static,
 
     /// A region variable.  Should not exist after typeck.
-    re_var(region_vid)
+    re_var(RegionVid)
 }
 
 enum bound_region {
@@ -505,7 +527,7 @@ enum sty {
     ty_ptr(mt),
     ty_rptr(region, mt),
     ty_rec(~[field]),
-    ty_fn(fn_ty),
+    ty_fn(FnTy),
     ty_trait(def_id, substs, vstore),
     ty_class(def_id, substs),
     ty_tup(~[t]),
@@ -567,13 +589,14 @@ enum param_bound {
     bound_trait(t),
 }
 
-enum ty_vid = uint;
-enum int_vid = uint;
-enum region_vid = uint;
+enum TyVid = uint;
+enum IntVid = uint;
+enum FnVid = uint;
+enum RegionVid = uint;
 
 enum InferTy {
-    TyVar(ty_vid),
-    IntVar(int_vid)
+    TyVar(TyVid),
+    IntVar(IntVid)
 }
 
 trait vid {
@@ -581,17 +604,22 @@ trait vid {
     pure fn to_str() -> ~str;
 }
 
-impl ty_vid: vid {
+impl TyVid: vid {
     pure fn to_uint() -> uint { *self }
     pure fn to_str() -> ~str { fmt!("<V%u>", self.to_uint()) }
 }
 
-impl int_vid: vid {
+impl IntVid: vid {
     pure fn to_uint() -> uint { *self }
     pure fn to_str() -> ~str { fmt!("<VI%u>", self.to_uint()) }
 }
 
-impl region_vid: vid {
+impl FnVid: vid {
+    pure fn to_uint() -> uint { *self }
+    pure fn to_str() -> ~str { fmt!("<F%u>", self.to_uint()) }
+}
+
+impl RegionVid: vid {
     pure fn to_uint() -> uint { *self }
     pure fn to_str() -> ~str { fmt!("%?", self) }
 }
@@ -600,14 +628,14 @@ impl InferTy {
     pure fn to_hash() -> uint {
         match self {
             TyVar(v) => v.to_uint() << 1,
-            IntVar(v) => (v.to_uint() << 1) + 1
+            IntVar(v) => (v.to_uint() << 1) + 1,
         }
     }
 
     pure fn to_str() -> ~str {
         match self {
             TyVar(v) => v.to_str(),
-            IntVar(v) => v.to_str()
+            IntVar(v) => v.to_str(),
         }
     }
 }
@@ -781,12 +809,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
       ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
       ty_tup(ts) => for ts.each |tt| { flags |= get(tt).flags; },
       ty_fn(ref f) => {
-        match f.proto {
+        match f.meta.proto {
             ty::proto_vstore(vstore_slice(r)) => flags |= rflags(r),
             ty::proto_bare | ty::proto_vstore(_) => {}
         }
-        for f.inputs.each |a| { flags |= get(a.ty).flags; }
-        flags |= get(f.output).flags;
+        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
+        flags |= get(f.sig.output).flags;
       }
     }
     let t = @{struct: st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
@@ -883,13 +911,12 @@ fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
     mk_t(cx, ty_unboxed_vec({ty: ty, mutbl: ast::m_imm}))
 }
 
-
 fn mk_rec(cx: ctxt, fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
 
 fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
 
 // take a copy because we want to own the various vectors inside
-fn mk_fn(cx: ctxt, +fty: fn_ty) -> t { mk_t(cx, ty_fn(fty)) }
+fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) }
 
 fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
          -> t {
@@ -902,9 +929,9 @@ fn mk_class(cx: ctxt, class_id: ast::def_id, +substs: substs) -> t {
     mk_t(cx, ty_class(class_id, substs))
 }
 
-fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_infer(cx, TyVar(v)) }
+fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
 
-fn mk_int_var(cx: ctxt, v: int_vid) -> t {
+fn mk_int_var(cx: ctxt, v: IntVid) -> t {
     mk_infer(cx, IntVar(v))
 }
 
@@ -976,8 +1003,8 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
       }
       ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(tt, f); } }
       ty_fn(ref ft) => {
-        for ft.inputs.each |a| { maybe_walk_ty(a.ty, f); }
-        maybe_walk_ty(ft.output, f);
+        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
+        maybe_walk_ty(ft.sig.output, f);
       }
       ty_uniq(tm) => { maybe_walk_ty(tm.ty, f); }
     }
@@ -995,58 +1022,61 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
     }
 
     match *sty {
-      ty_box(tm) => {
-        ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl})
-      }
-      ty_uniq(tm) => {
-        ty_uniq({ty: fldop(tm.ty), mutbl: tm.mutbl})
-      }
-      ty_ptr(tm) => {
-        ty_ptr({ty: fldop(tm.ty), mutbl: tm.mutbl})
-      }
-      ty_unboxed_vec(tm) => {
-        ty_unboxed_vec({ty: fldop(tm.ty), mutbl: tm.mutbl})
-      }
-      ty_evec(tm, vst) => {
-        ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
-      }
-      ty_enum(tid, ref substs) => {
-        ty_enum(tid, fold_substs(substs, fldop))
-      }
-      ty_trait(did, ref substs, vst) => {
-        ty_trait(did, fold_substs(substs, fldop), vst)
-      }
-      ty_rec(fields) => {
-        let new_fields = do vec::map(fields) |fl| {
-            let new_ty = fldop(fl.mt.ty);
-            let new_mt = {ty: new_ty, mutbl: fl.mt.mutbl};
-            {ident: fl.ident, mt: new_mt}
-        };
-        ty_rec(new_fields)
-      }
-      ty_tup(ts) => {
-        let new_ts = vec::map(ts, |tt| fldop(tt));
-        ty_tup(new_ts)
-      }
-      ty_fn(ref f) => {
-        let new_args = vec::map(f.inputs, |a| {
-            let new_ty = fldop(a.ty);
-            {mode: a.mode, ty: new_ty}
-        });
-        let new_output = fldop(f.output);
-        ty_fn({inputs: new_args, output: new_output,.. *f})
-      }
-      ty_rptr(r, tm) => {
-        ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
-      }
-      ty_class(did, ref substs) => {
-        ty_class(did, fold_substs(substs, fldop))
-      }
-      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
-      ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
-        *sty
-      }
+        ty_box(tm) => {
+            ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl})
+        }
+        ty_uniq(tm) => {
+            ty_uniq({ty: fldop(tm.ty), mutbl: tm.mutbl})
+        }
+        ty_ptr(tm) => {
+            ty_ptr({ty: fldop(tm.ty), mutbl: tm.mutbl})
+        }
+        ty_unboxed_vec(tm) => {
+            ty_unboxed_vec({ty: fldop(tm.ty), mutbl: tm.mutbl})
+        }
+        ty_evec(tm, vst) => {
+            ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
+        }
+        ty_enum(tid, ref substs) => {
+            ty_enum(tid, fold_substs(substs, fldop))
+        }
+        ty_trait(did, ref substs, vst) => {
+            ty_trait(did, fold_substs(substs, fldop), vst)
+        }
+        ty_rec(fields) => {
+            let new_fields = do vec::map(fields) |fl| {
+                let new_ty = fldop(fl.mt.ty);
+                let new_mt = {ty: new_ty, mutbl: fl.mt.mutbl};
+                {ident: fl.ident, mt: new_mt}
+            };
+            ty_rec(new_fields)
+        }
+        ty_tup(ts) => {
+            let new_ts = vec::map(ts, |tt| fldop(tt));
+            ty_tup(new_ts)
+        }
+        ty_fn(ref f) => {
+            let new_args = f.sig.inputs.map(|a| {
+                let new_ty = fldop(a.ty);
+                {mode: a.mode, ty: new_ty}
+            });
+            let new_output = fldop(f.sig.output);
+            ty_fn(FnTyBase {
+                meta: f.meta,
+                sig: FnSig {inputs: new_args, output: new_output}
+            })
+        }
+        ty_rptr(r, tm) => {
+            ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
+        }
+        ty_class(did, ref substs) => {
+            ty_class(did, fold_substs(substs, fldop))
+        }
+        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
+        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
+        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
+            *sty
+        }
     }
 }
 
@@ -1113,9 +1143,9 @@ fn fold_regions_and_ty(
       ty_trait(def_id, ref substs, vst) => {
         ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
       }
-      ty_fn(f) => {
+      ty_fn(ref f) => {
         let new_proto;
-        match f.proto {
+        match f.meta.proto {
             proto_bare =>
                 new_proto = proto_bare,
             proto_vstore(vstore_slice(r)) =>
@@ -1123,16 +1153,15 @@ fn fold_regions_and_ty(
             proto_vstore(old_vstore) =>
                 new_proto = proto_vstore(old_vstore)
         }
-
-        let new_args = vec::map(f.inputs, |a| {
+        let new_args = vec::map(f.sig.inputs, |a| {
             let new_ty = fldfnt(a.ty);
             {mode: a.mode, ty: new_ty}
         });
-        let new_output = fldfnt(f.output);
-        ty::mk_fn(cx, {
-            inputs: new_args,
-            output: new_output,
-            proto: new_proto,.. f
+        let new_output = fldfnt(f.sig.output);
+        ty::mk_fn(cx, FnTyBase {
+            meta: FnMeta {proto: new_proto, ..f.meta},
+            sig: FnSig {inputs: new_args,
+                        output: new_output}
         })
       }
       ref sty => {
@@ -1440,7 +1469,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
         accum
       }
       ty_fn(ref fty) => {
-        match fty.proto {
+        match fty.meta.proto {
           proto_bare | proto_vstore(vstore_slice(_)) => false,
           _ => true
         }
@@ -1667,8 +1696,8 @@ pure fn kind_is_owned(k: kind) -> bool {
     *k & KIND_MASK_OWNED == KIND_MASK_OWNED
 }
 
-fn proto_kind(p: fn_proto) -> kind {
-    match p {
+fn meta_kind(p: FnMeta) -> kind {
+    match p.proto { // XXX consider the kind bounds!
       proto_vstore(vstore_slice(_)) =>
         kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE),
       proto_vstore(vstore_box) =>
@@ -1753,7 +1782,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
       }
 
       // functions depend on the protocol
-      ty_fn(ref f) => proto_kind(f.proto),
+      ty_fn(ref f) => meta_kind(f.meta),
 
       // Those with refcounts raise noncopyable to copyable,
       // lower sendable to copyable. Therefore just set result to copyable.
@@ -2361,8 +2390,10 @@ pure fn hash_type_structure(st: &sty) -> uint {
       }
       ty_fn(ref f) => {
         let mut h = 27u;
-        for vec::each(f.inputs) |a| { h = hash_subty(h, a.ty); }
-        hash_subty(h, f.output)
+        for vec::each(f.sig.inputs) |a| {
+            h = hash_subty(h, a.ty);
+        }
+        hash_subty(h, f.sig.output)
       }
       ty_self => 28u,
       ty_infer(v) => hash_uint(29u, v.to_hash()),
@@ -2415,35 +2446,35 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
 // Type accessors for substructures of types
 fn ty_fn_args(fty: t) -> ~[arg] {
     match get(fty).struct {
-      ty_fn(ref f) => f.inputs,
+      ty_fn(ref f) => f.sig.inputs,
       _ => fail ~"ty_fn_args() called on non-fn type"
     }
 }
 
 fn ty_fn_proto(fty: t) -> fn_proto {
     match get(fty).struct {
-      ty_fn(ref f) => f.proto,
+      ty_fn(ref f) => f.meta.proto,
       _ => fail ~"ty_fn_proto() called on non-fn type"
     }
 }
 
 fn ty_fn_purity(fty: t) -> ast::purity {
     match get(fty).struct {
-      ty_fn(ref f) => f.purity,
+      ty_fn(ref f) => f.meta.purity,
       _ => fail ~"ty_fn_purity() called on non-fn type"
     }
 }
 
 pure fn ty_fn_ret(fty: t) -> t {
     match get(fty).struct {
-      ty_fn(ref f) => f.output,
+      ty_fn(ref f) => f.sig.output,
       _ => fail ~"ty_fn_ret() called on non-fn type"
     }
 }
 
 fn ty_fn_ret_style(fty: t) -> ast::ret_style {
     match get(fty).struct {
-      ty_fn(ref f) => f.ret_style,
+      ty_fn(ref f) => f.meta.ret_style,
       _ => fail ~"ty_fn_ret_style() called on non-fn type"
     }
 }
@@ -2463,8 +2494,8 @@ fn ty_region(ty: t) -> region {
 }
 
 // Returns a vec of all the input and output types of fty.
-fn tys_in_fn_ty(fty: &fn_ty) -> ~[t] {
-    vec::append_one(fty.inputs.map(|a| a.ty), fty.output)
+fn tys_in_fn_ty(fty: &FnTy) -> ~[t] {
+    vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output)
 }
 
 // Just checks whether it's a fn that returns bool,
@@ -2474,14 +2505,14 @@ fn is_pred_ty(fty: t) -> bool {
 }
 
 /*
-fn ty_var_id(typ: t) -> ty_vid {
+fn ty_var_id(typ: t) -> TyVid {
     match get(typ).struct {
       ty_infer(TyVar(vid)) => return vid,
       _ => { error!("ty_var_id called on non-var ty"); fail; }
     }
 }
 
-fn int_var_id(typ: t) -> int_vid {
+fn int_var_id(typ: t) -> IntVid {
     match get(typ).struct {
       ty_infer(IntVar(vid)) => return vid,
       _ => { error!("ty_var_integral_id called on ty other than \
@@ -2765,11 +2796,11 @@ fn param_tys_in_type(ty: t) -> ~[param_ty] {
     rslt
 }
 
-fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) {
+fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
 
     // Returns a vec of all the type variables occurring in `ty`. It may
     // contain duplicates.  (Integral type vars aren't counted.)
-    fn vars_in_type(ty: t) -> ~[ty_vid] {
+    fn vars_in_type(ty: t) -> ~[TyVid] {
         let mut rslt = ~[];
         do walk_ty(ty) |ty| {
             match get(ty).struct {
@@ -3561,20 +3592,16 @@ fn normalize_ty(cx: ctxt, t: t) -> t {
             // This type has a region. Get rid of it
             mk_rptr(cx, re_static, normalize_mt(cx, mt)),
 
-        ty_fn({purity: purity,
-               proto: proto_vstore(vstore),
-               bounds: bounds,
-               inputs: inputs,
-               output: output,
-               ret_style: ret_style}) =>
-            mk_fn(cx, {
-                purity: purity,
-                proto: proto_vstore(normalize_vstore(vstore)),
-                bounds: bounds,
-                inputs: inputs,
-                output: output,
-                ret_style: ret_style
-            }),
+        ty_fn(ref fn_ty) => {
+            let proto = match fn_ty.meta.proto {
+                proto_bare => proto_bare,
+                proto_vstore(vstore) => proto_vstore(normalize_vstore(vstore))
+            };
+            mk_fn(cx, FnTyBase {
+                meta: FnMeta {proto: proto, ..fn_ty.meta},
+                sig: fn_ty.sig
+            })
+        }
 
         ty_enum(did, r) =>
             match r.self_r {
@@ -3708,31 +3735,48 @@ impl vstore : cmp::Eq {
     }
 }
 
-impl fn_ty : cmp::Eq {
-    pure fn eq(&&other: fn_ty) -> bool {
+impl FnMeta : cmp::Eq {
+    pure fn eq(&&other: FnMeta) -> bool {
         self.purity == other.purity &&
         self.proto == other.proto &&
         self.bounds == other.bounds &&
-        self.inputs == other.inputs &&
-        self.output == other.output &&
         self.ret_style == other.ret_style
     }
 }
 
-impl ty_vid: cmp::Eq {
-    pure fn eq(&&other: ty_vid) -> bool {
+impl FnSig : cmp::Eq {
+    pure fn eq(&&other: FnSig) -> bool {
+        self.inputs == other.inputs &&
+        self.output == other.output
+    }
+}
+
+impl<M: cmp::Eq> FnTyBase<M> : cmp::Eq {
+    pure fn eq(&&other: FnTyBase<M>) -> bool {
+        self.meta == other.meta && self.sig == other.sig
+    }
+}
+
+impl TyVid: cmp::Eq {
+    pure fn eq(&&other: TyVid) -> bool {
+        *self == *other
+    }
+}
+
+impl IntVid: cmp::Eq {
+    pure fn eq(&&other: IntVid) -> bool {
         *self == *other
     }
 }
 
-impl int_vid: cmp::Eq {
-    pure fn eq(&&other: int_vid) -> bool {
+impl FnVid: cmp::Eq {
+    pure fn eq(&&other: FnVid) -> bool {
         *self == *other
     }
 }
 
-impl region_vid: cmp::Eq {
-    pure fn eq(&&other: region_vid) -> bool {
+impl RegionVid: cmp::Eq {
+    pure fn eq(&&other: RegionVid) -> bool {
         *self == *other
     }
 }
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 3f4ec261698..39d4a64f19f 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -255,38 +255,40 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
     let tcx = ccx.tcx;
     let main_t = ty::node_id_to_type(tcx, main_id);
     match ty::get(main_t).struct {
-      ty::ty_fn({purity: ast::impure_fn, proto: ty::proto_bare,
-                 inputs, output, ret_style: ast::return_val, _}) => {
-        match tcx.items.find(main_id) {
-         Some(ast_map::node_item(it,_)) => {
-             match it.node {
-               ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => {
-                  tcx.sess.span_err(main_span,
-                    ~"main function is not allowed to have type parameters");
-                  return;
-               }
-               _ => ()
-             }
-         }
-         _ => ()
-        }
-        let mut ok = ty::type_is_nil(output);
-        let num_args = vec::len(inputs);
-        ok &= num_args == 0u || num_args == 1u &&
-              arg_is_argv_ty(tcx, inputs[0]);
-        if !ok {
-                tcx.sess.span_err(main_span,
-                   fmt!("Wrong type in main function: found `%s`, \
-                   expected `extern fn(~[str]) -> ()` \
-                   or `extern fn() -> ()`",
+        ty::ty_fn(fn_ty) => {
+            match tcx.items.find(main_id) {
+                Some(ast_map::node_item(it,_)) => {
+                    match it.node {
+                        ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => {
+                            tcx.sess.span_err(
+                                main_span,
+                                ~"main function is not allowed \
+                                  to have type parameters");
+                            return;
+                        }
+                        _ => ()
+                    }
+                }
+                _ => ()
+            }
+            let mut ok = ty::type_is_nil(fn_ty.sig.output);
+            let num_args = vec::len(fn_ty.sig.inputs);
+            ok &= num_args == 0u || num_args == 1u &&
+                arg_is_argv_ty(tcx, fn_ty.sig.inputs[0]);
+            if !ok {
+                tcx.sess.span_err(
+                    main_span,
+                    fmt!("Wrong type in main function: found `%s`, \
+                          expected `extern fn(~[str]) -> ()` \
+                          or `extern fn() -> ()`",
                          ty_to_str(tcx, main_t)));
-         }
-      }
-      _ => {
-        tcx.sess.span_bug(main_span,
-                          ~"main has a non-function type: found `" +
+            }
+        }
+        _ => {
+            tcx.sess.span_bug(main_span,
+                              ~"main has a non-function type: found `" +
                               ty_to_str(tcx, main_t) + ~"`");
-      }
+        }
     }
 }
 
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index 933629bdf91..85bac78da97 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -45,6 +45,7 @@
 use check::fn_ctxt;
 use rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
 use rscope::{in_binding_rscope, region_scope, type_rscope};
+use ty::{FnTyBase, FnMeta, FnSig};
 
 trait ast_conv {
     fn tcx() -> ty::ctxt;
@@ -471,7 +472,7 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
     bounds: @~[ty::param_bound],
     decl: ast::fn_decl,
     expected_tys: expected_tys,
-    span: span) -> ty::fn_ty {
+    span: span) -> ty::FnTy {
 
     debug!("ty_of_fn_decl");
     do indent {
@@ -497,8 +498,14 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
 
         let proto = ast_proto_to_proto(self, rscope, span, ast_proto);
 
-        {purity: purity, proto: proto, bounds: bounds, inputs: input_tys,
-         output: output_ty, ret_style: decl.cf}
+        FnTyBase {
+            meta: FnMeta {purity: purity,
+                          proto: proto,
+                          bounds: bounds,
+                          ret_style: decl.cf},
+            sig: FnSig {inputs: input_tys,
+                        output: output_ty}
+        }
     }
 }
 
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index 7bdc1dd4adb..4ec13684f7e 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -68,7 +68,7 @@ type parameter).
 
 use astconv::{ast_conv, ast_path_to_ty, ast_ty_to_ty};
 use astconv::{ast_region_to_region};
-use middle::ty::{ty_vid, vid};
+use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig};
 use regionmanip::{replace_bound_regions_in_fn_ty};
 use rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
 use rscope::{in_binding_rscope, region_scope, type_rscope,
@@ -98,7 +98,7 @@ type self_info = {
 /// share the inherited fields.
 struct inherited {
     infcx: infer::infer_ctxt;
-    locals: hashmap<ast::node_id, ty_vid>;
+    locals: hashmap<ast::node_id, TyVid>;
     node_types: hashmap<ast::node_id, ty::t>;
     node_type_substs: hashmap<ast::node_id, ty::substs>;
     borrowings: hashmap<ast::node_id, ty::borrow>;
@@ -211,7 +211,7 @@ fn check_bare_fn(ccx: @crate_ctxt,
 
 fn check_fn(ccx: @crate_ctxt,
             self_info: Option<self_info>,
-            fn_ty: &ty::fn_ty,
+            fn_ty: &ty::FnTy,
             decl: ast::fn_decl,
             body: ast::blk,
             indirect_ret: bool,
@@ -231,8 +231,8 @@ fn check_fn(ccx: @crate_ctxt,
                                        |br| ty::re_free(body.node.id, br))
     };
 
-    let arg_tys = fn_ty.inputs.map(|a| a.ty);
-    let ret_ty = fn_ty.output;
+    let arg_tys = fn_ty.sig.inputs.map(|a| a.ty);
+    let ret_ty = fn_ty.sig.output;
 
     debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)",
            arg_tys.map(|a| ty_to_str(tcx, a)),
@@ -245,12 +245,12 @@ fn check_fn(ccx: @crate_ctxt,
     let fcx: @fn_ctxt = {
         let (purity, inherited) = match old_fcx {
             None => {
-                (fn_ty.purity,
+                (fn_ty.meta.purity,
                  blank_inherited(ccx))
             }
             Some(fcx) => {
-                (ty::determine_inherited_purity(fcx.purity, fn_ty.purity,
-                                                fn_ty.proto),
+                (ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity,
+                                                fn_ty.meta.proto),
                  fcx.inh)
             }
         };
@@ -943,9 +943,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
 
         // Grab the argument types, supplying fresh type variables
         // if the wrong number of arguments were supplied
-        let expected_arg_count = vec::len(fn_ty.inputs);
+        let expected_arg_count = vec::len(fn_ty.sig.inputs);
         let arg_tys = if expected_arg_count == supplied_arg_count {
-            fn_ty.inputs.map(|a| a.ty)
+            fn_ty.sig.inputs.map(|a| a.ty)
         } else {
             fcx.ccx.tcx.sess.span_err(
                 sp, fmt!("this function takes %u parameter%s but %u \
@@ -1031,9 +1031,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
 
         // Pull the return type out of the type of the function.
         match structure_of(fcx, sp, fty) {
-          ty::ty_fn(f) => {
-            bot |= (f.ret_style == ast::noreturn);
-            fcx.write_ty(call_expr_id, f.output);
+          ty::ty_fn(ref f) => {
+            bot |= (f.meta.ret_style == ast::noreturn);
+            fcx.write_ty(call_expr_id, f.sig.output);
             return bot;
           }
           _ => fcx.ccx.tcx.sess.span_fatal(sp, ~"calling non-function")
@@ -1242,10 +1242,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
                     replace_bound_regions_in_fn_ty(
                         tcx, @Nil, None, fn_ty,
                         |br| ty::re_bound(ty::br_cap_avoid(expr.id, @br)));
-                (Some({inputs:fn_ty.inputs,
-                       output:fn_ty.output}),
-                 fn_ty.purity,
-                 fn_ty.proto)
+                (Some({inputs: fn_ty.sig.inputs,
+                       output: fn_ty.sig.output}),
+                 fn_ty.meta.purity,
+                 fn_ty.meta.proto)
               }
               _ => {
                 (None, ast::impure_fn, ty::proto_vstore(ty::vstore_box))
@@ -1268,8 +1268,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         // Patch up the function declaration, if necessary.
         match ast_proto_opt {
           None => {
-            fn_ty.purity = expected_purity;
-            fn_ty.proto = expected_proto;
+            fn_ty.meta.purity = expected_purity;
+            fn_ty.meta.proto = expected_proto;
           }
           Some(_) => { }
         }
@@ -1643,16 +1643,20 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         let inner_ty = match expected_sty {
           Some(ty::ty_fn(fty)) => {
             match fcx.mk_subty(false, expr.span,
-                               fty.output, ty::mk_bool(tcx)) {
+                               fty.sig.output, ty::mk_bool(tcx)) {
               result::Ok(_) => (),
               result::Err(_) => {
                 tcx.sess.span_fatal(
                     expr.span, fmt!("a `loop` function's last argument \
                                      should return `bool`, not `%s`",
-                                    fcx.infcx().ty_to_str(fty.output)));
+                                    fcx.infcx().ty_to_str(fty.sig.output)));
               }
             }
-            ty::mk_fn(tcx, {output: ty::mk_nil(tcx),.. fty})
+            ty::mk_fn(tcx, FnTyBase {
+                meta: fty.meta,
+                sig: FnSig {output: ty::mk_nil(tcx),
+                            ..fty.sig}
+            })
           }
           _ => {
             tcx.sess.span_fatal(expr.span, ~"a `loop` function's last \
@@ -1675,8 +1679,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
             fcx, expr.span, fcx.node_ty(b.id));
         match ty::get(block_ty).struct {
           ty::ty_fn(fty) => {
-            fcx.write_ty(expr.id, ty::mk_fn(tcx, {output: ty::mk_bool(tcx),
-                                                  .. fty}));
+            fcx.write_ty(expr.id, ty::mk_fn(tcx, FnTyBase {
+                meta: fty.meta,
+                sig: FnSig {output: ty::mk_bool(tcx),
+                            ..fty.sig}
+            }))
           }
           _ => fail ~"expected fn type"
         }
@@ -2306,7 +2313,7 @@ fn self_ref(fcx: @fn_ctxt, id: ast::node_id) -> bool {
                         ast_util::is_self)
 }
 
-fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> ty_vid {
+fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> TyVid {
     match fcx.inh.locals.find(id) {
         Some(x) => x,
         _ => {
@@ -2571,20 +2578,18 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
                  arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
       }
       ~"frame_address" => {
-        let fty = ty::mk_fn(ccx.tcx, {
-            purity: ast::impure_fn,
-            proto:
-                ty::proto_vstore(ty::vstore_slice(
-                    ty::re_bound(ty::br_anon(0)))),
-            bounds: @~[],
-            inputs: ~[{
-                mode: ast::expl(ast::by_val),
-                ty: ty::mk_imm_ptr(
-                    ccx.tcx,
-                    ty::mk_mach_uint(ccx.tcx, ast::ty_u8))
-            }],
-            output: ty::mk_nil(ccx.tcx),
-            ret_style: ast::return_val
+        let fty = ty::mk_fn(ccx.tcx, FnTyBase {
+            meta: FnMeta {purity: ast::impure_fn,
+                          proto: ty::proto_vstore(ty::vstore_slice(
+                              ty::re_bound(ty::br_anon(0)))),
+                          bounds: @~[],
+                          ret_style: ast::return_val},
+            sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
+                                   ty: ty::mk_imm_ptr(
+                                       ccx.tcx,
+                                       ty::mk_mach_uint(ccx.tcx, ast::ty_u8))
+                                  }],
+                        output: ty::mk_nil(ccx.tcx)}
         });
         (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil(tcx))
       }
@@ -2597,11 +2602,14 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
         return;
       }
     };
-    let fty = ty::mk_fn(tcx, {purity: ast::impure_fn,
-                              proto: ty::proto_bare,
-                              bounds: @~[],
-                              inputs: inputs, output: output,
-                              ret_style: ast::return_val});
+    let fty = ty::mk_fn(tcx, FnTyBase {
+        meta: FnMeta {purity: ast::impure_fn,
+                      proto: ty::proto_bare,
+                      bounds: @~[],
+                      ret_style: ast::return_val},
+        sig: FnSig {inputs: inputs,
+                    output: output}
+    });
     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
     let i_n_tps = (*i_ty.bounds).len();
     if i_n_tps != n_tps {
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index b356a1b7f67..52e8578124d 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -2,7 +2,7 @@
 
 use coherence::get_base_type_def_id;
 use middle::resolve::{Impl, MethodInfo};
-use middle::ty::{mk_box, mk_rptr, mk_uniq};
+use middle::ty::{mk_box, mk_rptr, mk_uniq, FnTyBase, FnMeta, FnSig};
 use syntax::ast::{def_id,
                      sty_static, sty_box, sty_by_ref, sty_region, sty_uniq};
 use syntax::ast::{sty_value, by_ref, by_copy};
@@ -411,9 +411,12 @@ struct lookup {
 
     fn ty_from_did(did: ast::def_id) -> ty::t {
         match ty::get(ty::lookup_item_type(self.tcx(), did).ty).struct {
-          ty::ty_fn(fty) => {
-            ty::mk_fn(self.tcx(),
-                      {proto: ty::proto_vstore(ty::vstore_box),.. fty})
+            ty::ty_fn(ref fty) => {
+                ty::mk_fn(self.tcx(), FnTyBase {
+                    meta: FnMeta {proto: ty::proto_vstore(ty::vstore_box),
+                                  ..fty.meta},
+                    sig: fty.sig
+                })
           }
           _ => fail ~"ty_from_did: not function ty"
         }
@@ -553,8 +556,11 @@ struct lookup {
 
         // a bit hokey, but the method unbound has a bare protocol, whereas
         // a.b has a protocol like fn@() (perhaps eventually fn&()):
-        let fty = ty::mk_fn(tcx, {proto: ty::proto_vstore(ty::vstore_box),
-                                  .. m.fty});
+        let fty = ty::mk_fn(tcx, FnTyBase {
+            meta: FnMeta {proto: ty::proto_vstore(ty::vstore_box),
+                          ..m.fty.meta},
+            sig: m.fty.sig
+        });
 
         self.candidates.push(
             {self_ty: self.self_ty,
diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs
index 6b7a8b4e402..bdb5cc5749c 100644
--- a/src/rustc/middle/typeck/check/regionck.rs
+++ b/src/rustc/middle/typeck/check/regionck.rs
@@ -216,10 +216,13 @@ fn visit_expr(e: @ast::expr, &&rcx: @rcx, v: rvt) {
           result::Err(_) => return,   // Typechecking will fail anyhow.
           result::Ok(function_type) => {
             match ty::get(function_type).struct {
-              ty::ty_fn({
-                proto: proto_vstore(vstore_slice(region)), _
-              }) => {
-                constrain_free_variables(rcx, region, e);
+              ty::ty_fn(ref fn_ty) => {
+                  match fn_ty.meta.proto {
+                      proto_vstore(vstore_slice(region)) => {
+                          constrain_free_variables(rcx, region, e);
+                      }
+                      _ => {}
+                  }
               }
               _ => ()
             }
diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs
index 50666b92023..d7cbaa05588 100644
--- a/src/rustc/middle/typeck/check/regionmanip.rs
+++ b/src/rustc/middle/typeck/check/regionmanip.rs
@@ -9,9 +9,9 @@ fn replace_bound_regions_in_fn_ty(
     tcx: ty::ctxt,
     isr: isr_alist,
     self_info: Option<self_info>,
-    fn_ty: &ty::fn_ty,
+    fn_ty: &ty::FnTy,
     mapf: fn(ty::bound_region) -> ty::region) ->
-    {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::fn_ty} {
+    {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} {
 
     // Take self_info apart; the self_ty part is the only one we want
     // to update here.
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 7bde062008d..3b25e41d313 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -23,6 +23,7 @@ are represented as `ty_param()` instances.
 use astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty};
 use ast_util::trait_method_to_ty_method;
 use rscope::*;
+use ty::{FnTyBase, FnMeta, FnSig};
 
 fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
 
@@ -127,14 +128,14 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
                     let arg_ty = ccx.to_ty(rs, va.ty);
                     {mode: ast::expl(ast::by_copy), ty: arg_ty}
                 });
-                result_ty = Some(ty::mk_fn(tcx,
-                                           {purity: ast::pure_fn,
-                                            proto: ty::proto_vstore
-                                                (ty::vstore_box),
-                                            bounds: @~[],
-                                            inputs: args,
-                                            output: enum_ty,
-                                            ret_style: ast::return_val}));
+                result_ty = Some(ty::mk_fn(tcx, FnTyBase {
+                    meta: FnMeta {purity: ast::pure_fn,
+                                  proto: ty::proto_vstore(ty::vstore_box),
+                                  bounds: @~[],
+                                  ret_style: ast::return_val},
+                    sig: FnSig {inputs: args,
+                                output: enum_ty}
+                }));
             }
             ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {
                 result_ty = Some(enum_ty);
@@ -247,7 +248,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
                        trait_m: ty::method, trait_substs: ty::substs,
                        self_ty: ty::t) {
 
-    if impl_m.fty.purity != trait_m.fty.purity {
+    if impl_m.fty.meta.purity != trait_m.fty.meta.purity {
         tcx.sess.span_err(
             sp, fmt!("method `%s`'s purity does \
                           not match the trait method's \
@@ -268,12 +269,12 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
         return;
     }
 
-    if vec::len(impl_m.fty.inputs) != vec::len(trait_m.fty.inputs) {
+    if vec::len(impl_m.fty.sig.inputs) != vec::len(trait_m.fty.sig.inputs) {
         tcx.sess.span_err(sp,fmt!("method `%s` has %u parameters \
                                    but the trait has %u",
                                    tcx.sess.str_of(trait_m.ident),
-                                   vec::len(impl_m.fty.inputs),
-                                   vec::len(trait_m.fty.inputs)));
+                                   vec::len(impl_m.fty.sig.inputs),
+                                   vec::len(trait_m.fty.sig.inputs)));
         return;
     }
 
@@ -488,13 +489,15 @@ fn convert_struct(ccx: @crate_ctxt,
             {self_r: rscope::bound_self_region(rp),
              self_ty: None,
              tps: ty::ty_params_to_tys(tcx, tps)});
-        let t_ctor = ty::mk_fn(
-            tcx, {purity: ast::impure_fn,
-                  proto: ty::proto_vstore(ty::vstore_slice(ty::re_static)),
-                  bounds: @~[],
-                  inputs: t_args,
-                  output: t_res,
-                  ret_style: ast::return_val});
+        let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static));
+        let t_ctor = ty::mk_fn(tcx, FnTyBase {
+            meta: FnMeta {purity: ast::impure_fn,
+                          proto: proto,
+                          bounds: @~[],
+                          ret_style: ast::return_val},
+            sig: FnSig {inputs: t_args,
+                        output: t_res}
+        });
         write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
         tcx.tcache.insert(local_def(ctor.node.id),
                           {bounds: tpt.bounds,
@@ -755,12 +758,14 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
     let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, a, None) );
     let output_ty = ast_ty_to_ty(ccx, rb, decl.output);
 
-    let t_fn = ty::mk_fn(ccx.tcx, {purity: purity,
-                                   proto: ty::proto_bare,
-                                   bounds: @~[],
-                                   inputs: input_tys,
-                                   output: output_ty,
-                                   ret_style: ast::return_val});
+    let t_fn = ty::mk_fn(ccx.tcx, FnTyBase {
+        meta: FnMeta {purity: purity,
+                      proto: ty::proto_bare,
+                      bounds: @~[],
+                      ret_style: ast::return_val},
+        sig: FnSig {inputs: input_tys,
+                    output: output_ty}
+    });
     let tpt = {bounds: bounds, region_param: None, ty: t_fn};
     ccx.tcx.tcache.insert(def_id, tpt);
     return tpt;
diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs
index a658ef044df..07752df7b45 100644
--- a/src/rustc/middle/typeck/infer.rs
+++ b/src/rustc/middle/typeck/infer.rs
@@ -250,7 +250,7 @@ use std::smallintmap;
 use std::smallintmap::smallintmap;
 use std::map::hashmap;
 use middle::ty;
-use middle::ty::{ty_vid, int_vid, region_vid, vid,
+use middle::ty::{TyVid, IntVid, RegionVid, vid,
                  ty_int, ty_uint, get, terr_fn, TyVar, IntVar};
 use syntax::{ast, ast_util};
 use syntax::ast::{ret_style, purity};
@@ -312,11 +312,11 @@ enum infer_ctxt = @{
     // We instantiate vals_and_bindings with bounds<ty::t> because the
     // types that might instantiate a general type variable have an
     // order, represented by its upper and lower bounds.
-    ty_var_bindings: vals_and_bindings<ty::ty_vid, bounds<ty::t>>,
+    ty_var_bindings: vals_and_bindings<ty::TyVid, bounds<ty::t>>,
 
     // The types that might instantiate an integral type variable are
     // represented by an int_ty_set.
-    int_var_bindings: vals_and_bindings<ty::int_vid, int_ty_set>,
+    int_var_bindings: vals_and_bindings<ty::IntVid, int_ty_set>,
 
     // For region variables.
     region_vars: RegionVarBindings,
@@ -328,11 +328,11 @@ enum infer_ctxt = @{
 };
 
 enum fixup_err {
-    unresolved_int_ty(int_vid),
-    unresolved_ty(ty_vid),
-    cyclic_ty(ty_vid),
-    unresolved_region(region_vid),
-    region_var_bound_by_region_var(region_vid, region_vid)
+    unresolved_int_ty(IntVid),
+    unresolved_ty(TyVid),
+    cyclic_ty(TyVid),
+    unresolved_region(RegionVid),
+    region_var_bound_by_region_var(RegionVid, RegionVid)
 }
 
 fn fixup_err_to_str(f: fixup_err) -> ~str {
@@ -596,12 +596,12 @@ impl infer_ctxt {
 }
 
 impl infer_ctxt {
-    fn next_ty_var_id() -> ty_vid {
+    fn next_ty_var_id() -> TyVid {
         let id = *self.ty_var_counter;
         *self.ty_var_counter += 1u;
         self.ty_var_bindings.vals.insert(id,
                                          root({lb: None, ub: None}, 0u));
-        return ty_vid(id);
+        return TyVid(id);
     }
 
     fn next_ty_var() -> ty::t {
@@ -612,13 +612,13 @@ impl infer_ctxt {
         vec::from_fn(n, |_i| self.next_ty_var())
     }
 
-    fn next_int_var_id() -> int_vid {
+    fn next_int_var_id() -> IntVid {
         let id = *self.int_var_counter;
         *self.int_var_counter += 1u;
 
         self.int_var_bindings.vals.insert(id,
                               root(int_ty_set_all(), 0u));
-        return int_vid(id);
+        return IntVid(id);
     }
 
     fn next_int_var() -> ty::t {
diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs
index 2b194ebdf17..8199d7058ff 100644
--- a/src/rustc/middle/typeck/infer/combine.rs
+++ b/src/rustc/middle/typeck/infer/combine.rs
@@ -45,6 +45,7 @@
 // now.
 
 use to_str::to_str;
+use ty::{FnTyBase, FnMeta, FnSig};
 
 trait combine {
     fn infcx() -> infer_ctxt;
@@ -62,7 +63,9 @@ trait combine {
     fn self_tys(a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>>;
     fn substs(did: ast::def_id, as: &ty::substs,
               bs: &ty::substs) -> cres<ty::substs>;
-    fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres<ty::fn_ty>;
+    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy>;
+    fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
+    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta>;
     fn flds(a: ty::field, b: ty::field) -> cres<ty::field>;
     fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
     fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
@@ -302,37 +305,47 @@ fn super_vstores<C:combine>(
     }
 }
 
-fn super_fns<C:combine>(
-    self: &C, a_f: &ty::fn_ty, b_f: &ty::fn_ty) -> cres<ty::fn_ty> {
+fn super_fn_metas<C:combine>(
+    self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres<ty::FnMeta>
+{
+    do self.protos(a_f.proto, b_f.proto).chain |p| {
+        do self.ret_styles(a_f.ret_style, b_f.ret_style).chain |rs| {
+            do self.purities(a_f.purity, b_f.purity).chain |purity| {
+                Ok(FnMeta {purity: purity,
+                           proto: p,
+                           bounds: a_f.bounds, // XXX: This is wrong!
+                           ret_style: rs})
+            }
+        }
+    }
+}
 
+fn super_fn_sigs<C:combine>(
+    self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig>
+{
     fn argvecs<C:combine>(self: &C, a_args: ~[ty::arg],
                           b_args: ~[ty::arg]) -> cres<~[ty::arg]> {
 
         if vec::same_length(a_args, b_args) {
-            map_vec2(a_args, b_args, |a, b| self.args(a, b) )
+            map_vec2(a_args, b_args, |a, b| self.args(a, b))
         } else {
             Err(ty::terr_arg_count)
         }
     }
 
-    do self.protos(a_f.proto, b_f.proto).chain |p| {
-        do self.ret_styles(a_f.ret_style, b_f.ret_style).chain |rs| {
-            do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| {
-                do self.tys(a_f.output, b_f.output).chain |output| {
-                    do self.purities(a_f.purity, b_f.purity).chain |purity| {
-                    // FIXME: uncomment if #2588 doesn't get accepted:
-                    // self.infcx().constrvecs(a_f.constraints,
-                    //                         b_f.constraints).then {||
-                        Ok({purity: purity,
-                            proto: p,
-                            bounds: a_f.bounds, // XXX: This is wrong!
-                            inputs: inputs,
-                            output: output,
-                            ret_style: rs})
-                    // }
-                    }
-                }
-            }
+    do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| {
+        do self.tys(a_f.output, b_f.output).chain |output| {
+            Ok(FnSig {inputs: inputs, output: output})
+        }
+    }
+}
+
+fn super_fns<C:combine>(
+    self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres<ty::FnTy>
+{
+    do self.fn_metas(&a_f.meta, &b_f.meta).chain |m| {
+        do self.fn_sigs(&a_f.sig, &b_f.sig).chain |s| {
+            Ok(FnTyBase {meta: m, sig: s})
         }
     }
 }
diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs
index 7ef0bf91943..b69d85d9fe4 100644
--- a/src/rustc/middle/typeck/infer/glb.rs
+++ b/src/rustc/middle/typeck/infer/glb.rs
@@ -147,10 +147,18 @@ impl Glb: combine {
         super_args(&self, a, b)
     }
 
-    fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres<ty::fn_ty> {
+    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
         super_fns(&self, a, b)
     }
 
+    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
+        super_fn_metas(&self, a, b)
+    }
+
+    fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+        super_fn_sigs(&self, a, b)
+    }
+
     fn substs(did: ast::def_id,
               as: &ty::substs,
               bs: &ty::substs) -> cres<ty::substs> {
diff --git a/src/rustc/middle/typeck/infer/lattice.rs b/src/rustc/middle/typeck/infer/lattice.rs
index 5fc9ee8d1a7..49b2e57e2aa 100644
--- a/src/rustc/middle/typeck/infer/lattice.rs
+++ b/src/rustc/middle/typeck/infer/lattice.rs
@@ -68,7 +68,7 @@ fn lattice_tys<L:lattice_ops combine>(
 }
 
 fn lattice_vars<L:lattice_ops combine>(
-    self: &L, +a_t: ty::t, +a_vid: ty::ty_vid, +b_vid: ty::ty_vid,
+    self: &L, +a_t: ty::t, +a_vid: ty::TyVid, +b_vid: ty::TyVid,
     c_ts: fn(ty::t, ty::t) -> cres<ty::t>) -> cres<ty::t> {
 
     // The comments in this function are written for LUB and types,
@@ -112,7 +112,7 @@ fn lattice_vars<L:lattice_ops combine>(
 }
 
 fn lattice_var_and_t<L:lattice_ops combine>(
-    self: &L, a_id: ty::ty_vid, b: ty::t,
+    self: &L, a_id: ty::TyVid, b: ty::t,
     c_ts: fn(ty::t, ty::t) -> cres<ty::t>) -> cres<ty::t> {
 
     let vb = &self.infcx().ty_var_bindings;
diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs
index 21e2a9febec..0c2f9ca6b13 100644
--- a/src/rustc/middle/typeck/infer/lub.rs
+++ b/src/rustc/middle/typeck/infer/lub.rs
@@ -126,10 +126,18 @@ impl Lub: combine {
         super_args(&self, a, b)
     }
 
-    fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres<ty::fn_ty> {
+    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
         super_fns(&self, a, b)
     }
 
+    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
+        super_fn_metas(&self, a, b)
+    }
+
+    fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+        super_fn_sigs(&self, a, b)
+    }
+
     fn substs(did: ast::def_id,
               as: &ty::substs,
               bs: &ty::substs) -> cres<ty::substs> {
diff --git a/src/rustc/middle/typeck/infer/region_var_bindings.rs b/src/rustc/middle/typeck/infer/region_var_bindings.rs
index 70dd5777e3d..b34ffef811a 100644
--- a/src/rustc/middle/typeck/infer/region_var_bindings.rs
+++ b/src/rustc/middle/typeck/infer/region_var_bindings.rs
@@ -312,7 +312,7 @@ use std::map::{hashmap, uint_hash};
 use std::cell::{Cell, empty_cell};
 use std::list::{List, Nil, Cons};
 
-use ty::{region, region_vid, hash_region};
+use ty::{region, RegionVid, hash_region};
 use region::is_subregion_of;
 use syntax::codemap;
 use to_str::to_str;
@@ -324,9 +324,9 @@ export lub_regions;
 export glb_regions;
 
 enum Constraint {
-    ConstrainVarSubVar(region_vid, region_vid),
-    ConstrainRegSubVar(region, region_vid),
-    ConstrainVarSubReg(region_vid, region)
+    ConstrainVarSubVar(RegionVid, RegionVid),
+    ConstrainRegSubVar(region, RegionVid),
+    ConstrainVarSubReg(RegionVid, region)
 }
 
 impl Constraint: cmp::Eq {
@@ -361,12 +361,12 @@ impl TwoRegions: cmp::Eq {
 
 enum UndoLogEntry {
     Snapshot,
-    AddVar(region_vid),
+    AddVar(RegionVid),
     AddConstraint(Constraint),
     AddCombination(CombineMap, TwoRegions)
 }
 
-type CombineMap = hashmap<TwoRegions, region_vid>;
+type CombineMap = hashmap<TwoRegions, RegionVid>;
 
 struct RegionVarBindings {
     tcx: ty::ctxt;
@@ -470,10 +470,10 @@ impl RegionVarBindings {
         self.var_spans.len()
     }
 
-    fn new_region_var(span: span) -> region_vid {
+    fn new_region_var(span: span) -> RegionVid {
         let id = self.num_vars();
         self.var_spans.push(span);
-        let vid = region_vid(id);
+        let vid = RegionVid(id);
         if self.in_snapshot() {
             self.undo_log.push(AddVar(vid));
         }
@@ -568,7 +568,7 @@ impl RegionVarBindings {
         }
     }
 
-    fn resolve_var(rid: region_vid) -> ty::region {
+    fn resolve_var(rid: RegionVid) -> ty::region {
         debug!("RegionVarBindings: resolve_var(%?)", rid);
         if self.values.is_empty() {
             self.tcx.sess.span_bug(
@@ -857,7 +857,7 @@ impl RegionVarBindings {
         return graph;
 
         fn insert_edge(graph: &mut Graph,
-                       node_id: region_vid,
+                       node_id: RegionVid,
                        edge_dir: Direction,
                        edge_idx: uint) {
             let edge_dir = edge_dir as uint;
@@ -893,7 +893,7 @@ impl RegionVarBindings {
     }
 
     fn expand_node(a_region: region,
-                   b_vid: region_vid,
+                   b_vid: RegionVid,
                    b_node: &GraphNode) -> bool {
         debug!("expand_node(%?, %? == %?)",
                a_region, b_vid, b_node.value);
@@ -950,7 +950,7 @@ impl RegionVarBindings {
         }
     }
 
-    fn contract_node(a_vid: region_vid,
+    fn contract_node(a_vid: RegionVid,
                      a_node: &GraphNode,
                      b_region: region) -> bool {
         debug!("contract_node(%? == %?/%?, %?)",
@@ -980,7 +980,7 @@ impl RegionVarBindings {
         };
 
         fn check_node(self: &RegionVarBindings,
-                      a_vid: region_vid,
+                      a_vid: RegionVid,
                       a_node: &GraphNode,
                       a_region: region,
                       b_region: region) -> bool {
@@ -993,7 +993,7 @@ impl RegionVarBindings {
         }
 
         fn adjust_node(self: &RegionVarBindings,
-                       a_vid: region_vid,
+                       a_vid: RegionVid,
                        a_node: &GraphNode,
                        a_region: region,
                        b_region: region) -> bool {
@@ -1051,7 +1051,7 @@ impl RegionVarBindings {
               }
 
               ErrorValue => {
-                let node_vid = region_vid(idx);
+                let node_vid = RegionVid(idx);
                 match node.classification {
                   Expanding => {
                     self.report_error_for_expanding_node(
@@ -1078,7 +1078,7 @@ impl RegionVarBindings {
 
     fn report_error_for_expanding_node(graph: &Graph,
                                        dup_map: TwoRegionsMap,
-                                       node_idx: region_vid) {
+                                       node_idx: RegionVid) {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
         let lower_bounds =
@@ -1130,7 +1130,7 @@ impl RegionVarBindings {
 
     fn report_error_for_contracting_node(graph: &Graph,
                                          dup_map: TwoRegionsMap,
-                                         node_idx: region_vid) {
+                                         node_idx: RegionVid) {
         // Errors in contracting nodes result from two upper-bounds
         // that have no intersection.
         let upper_bounds = self.collect_concrete_regions(graph, node_idx,
@@ -1182,7 +1182,7 @@ impl RegionVarBindings {
     }
 
     fn collect_concrete_regions(graph: &Graph,
-                                orig_node_idx: region_vid,
+                                orig_node_idx: RegionVid,
                                 dir: Direction) -> ~[SpannedRegion] {
         let set = uint_hash();
         let mut stack = ~[orig_node_idx];
@@ -1224,7 +1224,7 @@ impl RegionVarBindings {
     }
 
     fn each_edge(graph: &Graph,
-                 node_idx: region_vid,
+                 node_idx: RegionVid,
                  dir: Direction,
                  op: fn(edge: &GraphEdge) -> bool) {
         let mut edge_idx = graph.nodes[*node_idx].head_edge[dir as uint];
diff --git a/src/rustc/middle/typeck/infer/resolve.rs b/src/rustc/middle/typeck/infer/resolve.rs
index 8d6841357c0..e77b5a52aaf 100644
--- a/src/rustc/middle/typeck/infer/resolve.rs
+++ b/src/rustc/middle/typeck/infer/resolve.rs
@@ -55,7 +55,7 @@ type resolve_state_ = {
     infcx: infer_ctxt,
     modes: uint,
     mut err: Option<fixup_err>,
-    mut v_seen: ~[ty_vid]
+    mut v_seen: ~[TyVid]
 };
 
 enum resolve_state {
@@ -153,14 +153,14 @@ impl resolve_state {
         }
     }
 
-    fn resolve_region_var(rid: region_vid) -> ty::region {
+    fn resolve_region_var(rid: RegionVid) -> ty::region {
         if !self.should(resolve_rvar) {
             return ty::re_var(rid)
         }
         self.infcx.region_vars.resolve_var(rid)
     }
 
-    fn assert_not_rvar(rid: region_vid, r: ty::region) {
+    fn assert_not_rvar(rid: RegionVid, r: ty::region) {
         match r {
           ty::re_var(rid2) => {
             self.err = Some(region_var_bound_by_region_var(rid, rid2));
@@ -169,7 +169,7 @@ impl resolve_state {
         }
     }
 
-    fn resolve_ty_var(vid: ty_vid) -> ty::t {
+    fn resolve_ty_var(vid: TyVid) -> ty::t {
         if vec::contains(self.v_seen, vid) {
             self.err = Some(cyclic_ty(vid));
             return ty::mk_var(self.infcx.tcx, vid);
@@ -202,7 +202,7 @@ impl resolve_state {
         }
     }
 
-    fn resolve_int_var(vid: int_vid) -> ty::t {
+    fn resolve_int_var(vid: IntVid) -> ty::t {
         if !self.should(resolve_ivar) {
             return ty::mk_int_var(self.infcx.tcx, vid);
         }
diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs
index f3853134a37..8c83f03838a 100644
--- a/src/rustc/middle/typeck/infer/sub.rs
+++ b/src/rustc/middle/typeck/infer/sub.rs
@@ -124,7 +124,7 @@ impl Sub: combine {
         }
     }
 
-    fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres<ty::fn_ty> {
+    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
         // Rather than checking the subtype relationship between `a` and `b`
         // as-is, we need to do some extra work here in order to make sure
         // that function subtyping works correctly with respect to regions
@@ -171,6 +171,14 @@ impl Sub: combine {
         super_flds(&self, a, b)
     }
 
+    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
+        super_fn_metas(&self, a, b)
+    }
+
+    fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+        super_fn_sigs(&self, a, b)
+    }
+
     fn vstores(vk: ty::terr_vstore_kind,
                a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
         super_vstores(&self, vk, a, b)
diff --git a/src/rustc/middle/typeck/infer/unify.rs b/src/rustc/middle/typeck/infer/unify.rs
index e8e834cfc57..65cbcdcb40a 100644
--- a/src/rustc/middle/typeck/infer/unify.rs
+++ b/src/rustc/middle/typeck/infer/unify.rs
@@ -113,7 +113,7 @@ fn merge_bnds<C: combine>(
 
 fn set_var_to_merged_bounds<C: combine>(
     self: &C,
-    v_id: ty::ty_vid,
+    v_id: ty::TyVid,
     a: bounds<ty::t>,
     b: bounds<ty::t>,
     rank: uint) -> ures {
@@ -175,8 +175,8 @@ fn set_var_to_merged_bounds<C: combine>(
 /// subtle and tricky process, as described in detail at the top
 /// of infer.rs
 fn var_sub_var<C: combine>(self: &C,
-                           a_id: ty::ty_vid,
-                           b_id: ty::ty_vid) -> ures {
+                           a_id: ty::TyVid,
+                           b_id: ty::TyVid) -> ures {
     let vb = &self.infcx().ty_var_bindings;
 
     // Need to make sub_id a subtype of sup_id.
@@ -241,7 +241,7 @@ fn var_sub_var<C: combine>(self: &C,
 }
 
 /// make variable a subtype of T
-fn var_sub_t<C: combine>(self: &C, a_id: ty::ty_vid, b: ty::t) -> ures {
+fn var_sub_t<C: combine>(self: &C, a_id: ty::TyVid, b: ty::t) -> ures {
 
     let vb = &self.infcx().ty_var_bindings;
     let nde_a = self.infcx().get(vb, a_id);
@@ -257,7 +257,7 @@ fn var_sub_t<C: combine>(self: &C, a_id: ty::ty_vid, b: ty::t) -> ures {
 }
 
 /// make T a subtype of variable
-fn t_sub_var<C: combine>(self: &C, a: ty::t, b_id: ty::ty_vid) -> ures {
+fn t_sub_var<C: combine>(self: &C, a: ty::t, b_id: ty::TyVid) -> ures {
 
     let vb = &self.infcx().ty_var_bindings;
     let a_bounds = {lb: Some(a), ub: None};
@@ -294,7 +294,7 @@ fn bnds<C: combine>(
 // Integral variables
 
 impl infer_ctxt {
-    fn int_vars(a_id: ty::int_vid, b_id: ty::int_vid) -> ures {
+    fn int_vars(a_id: ty::IntVid, b_id: ty::IntVid) -> ures {
         let vb = &self.int_var_bindings;
 
         let nde_a = self.get(vb, a_id);
@@ -340,7 +340,7 @@ impl infer_ctxt {
         uok()
     }
 
-    fn int_var_sub_t(a_id: ty::int_vid, b: ty::t) -> ures {
+    fn int_var_sub_t(a_id: ty::IntVid, b: ty::t) -> ures {
         assert ty::type_is_integral(b);
 
         let vb = &self.int_var_bindings;
@@ -358,7 +358,7 @@ impl infer_ctxt {
         uok()
     }
 
-    fn t_sub_int_var(a: ty::t, b_id: ty::int_vid) -> ures {
+    fn t_sub_int_var(a: ty::t, b_id: ty::IntVid) -> ures {
         assert ty::type_is_integral(a);
         let vb = &self.int_var_bindings;
 
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index bb54e9df19b..f78495ef198 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -283,8 +283,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
     }
     fn method_to_str(cx: ctxt, m: method) -> ~str {
         return fn_to_str(
-            cx, m.fty.purity, m.fty.proto, Some(m.ident), m.fty.inputs,
-            m.fty.output, m.fty.ret_style) + ~";";
+            cx, m.fty.meta.purity, m.fty.meta.proto, Some(m.ident),
+            m.fty.sig.inputs, m.fty.sig.output,
+            m.fty.meta.ret_style) + ~";";
     }
     fn field_to_str(cx: ctxt, f: field) -> ~str {
         return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt);
@@ -331,9 +332,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         for elems.each |elem| { vec::push(strs, ty_to_str(cx, elem)); }
         ~"(" + str::connect(strs, ~",") + ~")"
       }
-      ty_fn(f) => {
-        fn_to_str(cx, f.purity, f.proto, None, f.inputs,
-                  f.output, f.ret_style)
+      ty_fn(ref f) => {
+        fn_to_str(cx, f.meta.purity, f.meta.proto, None, f.sig.inputs,
+                  f.sig.output, f.meta.ret_style)
       }
       ty_infer(infer_ty) => infer_ty.to_str(),
       ty_param({idx: id, _}) => {