]> git.lizzy.rs Git - rust.git/commitdiff
Reorganize some code in typeck
authorMarijn Haverbeke <marijnh@gmail.com>
Tue, 13 Dec 2011 14:28:22 +0000 (15:28 +0100)
committerMarijn Haverbeke <marijnh@gmail.com>
Tue, 13 Dec 2011 14:28:22 +0000 (15:28 +0100)
This should cut down a lot on the amount of closures being allocated, and removes
some duplicated code.

src/comp/middle/typeck.rs

index feaa1215d872468f86f88e788c426c8910e6f790..0bef6035016f506e55a3fa7f991764dc831bf82e 100644 (file)
@@ -48,9 +48,6 @@
      ccx: @crate_ctxt};
 
 
-// Used for ast_ty_to_ty() below.
-type ty_getter = fn@(ast::def_id) -> ty::ty_param_kinds_and_ty;
-
 fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> int {
     alt fcx.locals.find(id) {
       some(x) { x }
@@ -229,11 +226,32 @@ fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode,
       _ { m }
     }
 }
-fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty)
-    -> ty::t {
-    fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg)
+
+tag mode { m_collect; m_check; m_check_tyvar(@fn_ctxt); }
+
+fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
+    fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id)
+        -> ty::ty_param_kinds_and_ty {
+        alt mode {
+          m_check. | m_check_tyvar(_) { ty::lookup_item_type(tcx, id) }
+          m_collect. {
+            if id.crate != ast::local_crate { csearch::get_type(tcx, id) }
+            else {
+                alt tcx.items.find(id.node) {
+                  some(ast_map::node_item(item)) {
+                    ty_of_item(tcx, mode, item)
+                  }
+                  some(ast_map::node_native_item(native_item)) {
+                    ty_of_native_item(tcx, mode, native_item)
+                  }
+                }
+            }
+          }
+        }
+    }
+    fn ast_arg_to_arg(tcx: ty::ctxt, mode: mode, arg: ast::ty_arg)
         -> {mode: ty::mode, ty: ty::t} {
-        let ty = ast_ty_to_ty(tcx, getter, arg.node.ty);
+        let ty = ast_ty_to_ty(tcx, mode, arg.node.ty);
         ret {mode: default_arg_mode_for_ty(tcx, arg.node.mode, ty), ty: ty};
     }
     alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
@@ -248,15 +266,15 @@ fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg)
     } /* go on */
 
     tcx.ast_ty_to_ty_cache.insert(ast_ty, none::<ty::t>);
-    fn ast_mt_to_mt(tcx: ty::ctxt, getter: ty_getter, mt: ast::mt) -> ty::mt {
-        ret {ty: ast_ty_to_ty(tcx, getter, mt.ty), mut: mt.mut};
+    fn ast_mt_to_mt(tcx: ty::ctxt, mode: mode, mt: ast::mt) -> ty::mt {
+        ret {ty: ast_ty_to_ty(tcx, mode, mt.ty), mut: mt.mut};
     }
-    fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
+    fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
                    id: ast::def_id, args: [@ast::ty]) -> ty::t {
         // TODO: maybe record cname chains so we can do
         // "foo = int" like OCaml?
 
-        let ty_param_kinds_and_ty = getter(id);
+        let ty_param_kinds_and_ty = getter(tcx, mode, id);
         if vec::len(ty_param_kinds_and_ty.kinds) == 0u {
             ret ty_param_kinds_and_ty.ty;
         }
@@ -268,7 +286,7 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
                                      polymorphic type");
         }
         for ast_ty: @ast::ty in args {
-            param_bindings += [ast_ty_to_ty(tcx, getter, ast_ty)];
+            param_bindings += [ast_ty_to_ty(tcx, mode, ast_ty)];
         }
         let typ =
             ty::substitute_type_params(tcx, param_bindings,
@@ -286,25 +304,25 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
       ast::ty_float(ft) { typ = ty::mk_mach_float(tcx, ft); }
       ast::ty_str. { typ = ty::mk_str(tcx); }
       ast::ty_box(mt) {
-        typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, getter, mt));
+        typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, mode, mt));
       }
       ast::ty_uniq(mt) {
-        typ = ty::mk_uniq(tcx, ast_mt_to_mt(tcx, getter, mt));
+        typ = ty::mk_uniq(tcx, ast_mt_to_mt(tcx, mode, mt));
       }
       ast::ty_vec(mt) {
-        typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, getter, mt));
+        typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, mode, mt));
       }
       ast::ty_ptr(mt) {
-        typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt));
+        typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt));
       }
       ast::ty_tup(fields) {
-        let flds = vec::map(bind ast_ty_to_ty(tcx, getter, _), fields);
+        let flds = vec::map(bind ast_ty_to_ty(tcx, mode, _), fields);
         typ = ty::mk_tup(tcx, flds);
       }
       ast::ty_rec(fields) {
         let flds: [field] = [];
         for f: ast::ty_field in fields {
-            let tm = ast_mt_to_mt(tcx, getter, f.node.mt);
+            let tm = ast_mt_to_mt(tcx, mode, f.node.mt);
             flds += [{ident: f.node.ident, mt: tm}];
         }
         typ = ty::mk_rec(tcx, flds);
@@ -312,9 +330,9 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
       ast::ty_fn(proto, inputs, output, cf, constrs) {
         let i = [];
         for ta: ast::ty_arg in inputs {
-            i += [ast_arg_to_arg(tcx, getter, ta)];
+            i += [ast_arg_to_arg(tcx, mode, ta)];
         }
-        let out_ty = ast_ty_to_ty(tcx, getter, output);
+        let out_ty = ast_ty_to_ty(tcx, mode, output);
 
         let out_constrs = [];
         for constr: @ast::constr in constrs {
@@ -325,9 +343,9 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
       ast::ty_path(path, id) {
         alt tcx.def_map.find(id) {
           some(ast::def_ty(id)) {
-            typ = instantiate(tcx, ast_ty.span, getter, id, path.node.types);
+            typ = instantiate(tcx, ast_ty.span, mode, id, path.node.types);
           }
-          some(ast::def_native_ty(id)) { typ = getter(id).ty; }
+          some(ast::def_native_ty(id)) { typ = getter(tcx, mode, id).ty; }
           some(ast::def_ty_param(id, k)) { typ = ty::mk_param(tcx, id, k); }
           some(_) {
             tcx.sess.span_fatal(ast_ty.span,
@@ -344,9 +362,9 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
         for m: ast::ty_method in meths {
             let ins = [];
             for ta: ast::ty_arg in m.node.inputs {
-                ins += [ast_arg_to_arg(tcx, getter, ta)];
+                ins += [ast_arg_to_arg(tcx, mode, ta)];
             }
-            let out = ast_ty_to_ty(tcx, getter, m.node.output);
+            let out = ast_ty_to_ty(tcx, mode, m.node.output);
 
             let out_constrs = [];
             for constr: @ast::constr in m.node.constrs {
@@ -368,10 +386,14 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
         for constr: @ast::ty_constr in cs {
             out_cs += [ty::ast_constr_to_constr(tcx, constr)];
         }
-        typ = ty::mk_constr(tcx, ast_ty_to_ty(tcx, getter, t), out_cs);
+        typ = ty::mk_constr(tcx, ast_ty_to_ty(tcx, mode, t), out_cs);
       }
       ast::ty_infer. {
-        tcx.sess.span_bug(ast_ty.span, "found ty_infer in unexpected place");
+        alt mode {
+          m_check_tyvar(fcx) { ret next_ty_var(fcx); }
+          _ { tcx.sess.span_bug(ast_ty.span,
+                                "found ty_infer in unexpected place"); }
+        }
       }
     }
     alt cname {
@@ -382,16 +404,160 @@ fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter,
     ret typ;
 }
 
+fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
+    -> ty::ty_param_kinds_and_ty {
+    let no_kinds: [ast::kind] = [];
+    alt it.node {
+      ast::item_const(t, _) {
+        let typ = ast_ty_to_ty(tcx, mode, t);
+        let tpt = {kinds: no_kinds, ty: typ};
+        tcx.tcache.insert(local_def(it.id), tpt);
+        ret tpt;
+      }
+      ast::item_fn(fn_info, tps) {
+        ret ty_of_fn_decl(tcx, mode, fn_info.decl, fn_info.proto,
+                          tps, some(local_def(it.id)));
+      }
+      ast::item_obj(ob, tps, _) {
+        let t_obj = ty_of_obj(tcx, mode, it.ident, ob, tps);
+        tcx.tcache.insert(local_def(it.id), t_obj);
+        ret t_obj;
+      }
+      ast::item_ty(t, tps) {
+        alt tcx.tcache.find(local_def(it.id)) {
+          some(tpt) { ret tpt; }
+          none. { }
+        }
+        // Tell ast_ty_to_ty() that we want to perform a recursive
+        // call to resolve any named types.
+
+        let typ = ast_ty_to_ty(tcx, mode, t);
+        let tpt = {kinds: ty_param_kinds(tps), ty: typ};
+        tcx.tcache.insert(local_def(it.id), tpt);
+        ret tpt;
+      }
+      ast::item_res(f, _, tps, _) {
+        let t_arg = ty_of_arg(tcx, mode, f.decl.inputs[0]);
+        let t_res =
+            {kinds: ty_param_kinds(tps),
+             ty: ty::mk_res(tcx, local_def(it.id), t_arg.ty,
+                            mk_ty_params(tcx, tps))};
+        tcx.tcache.insert(local_def(it.id), t_res);
+        ret t_res;
+      }
+      ast::item_tag(_, tps) {
+        // Create a new generic polytype.
+        let subtys: [ty::t] = mk_ty_params(tcx, tps);
+        let t = ty::mk_tag(tcx, local_def(it.id), subtys);
+        let tpt = {kinds: ty_param_kinds(tps), ty: t};
+        tcx.tcache.insert(local_def(it.id), tpt);
+        ret tpt;
+      }
+      ast::item_mod(_) { fail; }
+      ast::item_native_mod(_) { fail; }
+    }
+}
+fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
+    -> ty::ty_param_kinds_and_ty {
+    let no_kinds: [ast::kind] = [];
+    alt it.node {
+      ast::native_item_fn(fn_decl, params) {
+        ret ty_of_native_fn_decl(tcx, mode, fn_decl, params,
+                                 ast_util::local_def(it.id));
+      }
+      ast::native_item_ty. {
+        alt tcx.tcache.find(local_def(it.id)) {
+          some(tpt) { ret tpt; }
+          none. { }
+        }
+        let t = ty::mk_native(tcx, ast_util::local_def(it.id));
+        let tpt = {kinds: no_kinds, ty: t};
+        tcx.tcache.insert(local_def(it.id), tpt);
+        ret tpt;
+      }
+    }
+}
+fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg {
+    let ty = ast_ty_to_ty(tcx, mode, a.ty);
+    {mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty}
+}
+fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
+           proto: ast::proto, ty_params: [ast::ty_param],
+           def_id: option::t<ast::def_id>) -> ty::ty_param_kinds_and_ty {
+    let input_tys = [];
+    for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
+    let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
+
+    let out_constrs = [];
+    for constr: @ast::constr in decl.constraints {
+        out_constrs += [ty::ast_constr_to_constr(tcx, constr)];
+    }
+    let t_fn = ty::mk_fn(tcx, proto, input_tys, output_ty,
+                         decl.cf, out_constrs);
+    let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
+    alt def_id { some(did) { tcx.tcache.insert(did, tpt); } _ { } }
+    ret tpt;
+}
+fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
+                  ty_params: [ast::ty_param], def_id: ast::def_id)
+    -> ty::ty_param_kinds_and_ty {
+    let input_tys = [];
+    for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
+    let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
+
+    let t_fn = ty::mk_native_fn(tcx, input_tys, output_ty);
+    let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
+    tcx.tcache.insert(def_id, tpt);
+    ret tpt;
+}
+fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
+    let inputs = vec::map({|i| ty_of_arg(tcx, mode, i)},
+                          m.node.meth.decl.inputs);
+    let output = ast_ty_to_ty(tcx, mode, m.node.meth.decl.output);
+
+    let out_constrs = [];
+    for constr: @ast::constr in m.node.meth.decl.constraints {
+        out_constrs += [ty::ast_constr_to_constr(tcx, constr)];
+    }
+    ret {proto: m.node.meth.proto,
+         ident: m.node.ident,
+         inputs: inputs,
+         output: output,
+         cf: m.node.meth.decl.cf,
+         constrs: out_constrs};
+}
+fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
+        ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty {
+    let methods = ty_of_obj_methods(tcx, mode, ob);
+    let t_obj = ty::mk_obj(tcx, ty::sort_methods(methods));
+    t_obj = ty::rename(tcx, t_obj, id);
+    ret {kinds: ty_param_kinds(ty_params), ty: t_obj};
+}
+fn ty_of_obj_methods(tcx: ty::ctxt, mode: mode, object: ast::_obj)
+    -> [ty::method] {
+    vec::map({|m| ty_of_method(tcx, mode, m)}, object.methods)
+}
+fn ty_of_obj_ctor(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
+            ctor_id: ast::node_id, ty_params: [ast::ty_param])
+    -> ty::ty_param_kinds_and_ty {
+    let t_obj = ty_of_obj(tcx, mode, id, ob, ty_params);
+    let t_inputs: [arg] = [];
+    for f: ast::obj_field in ob.fields {
+        let t_field = ast_ty_to_ty(tcx, mode, f.ty);
+        t_inputs += [{mode: ast::by_copy, ty: t_field}];
+    }
+    let t_fn = ty::mk_fn(tcx, ast::proto_shared(ast::sugar_normal),
+                         t_inputs, t_obj.ty,
+                         ast::return_val, []);
+    let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
+    tcx.tcache.insert(local_def(ctor_id), tpt);
+    ret tpt;
+}
 
 // A convenience function to use a crate_ctxt to resolve names for
 // ast_ty_to_ty.
 fn ast_ty_to_ty_crate(ccx: @crate_ctxt, &&ast_ty: @ast::ty) -> ty::t {
-    fn getter(ccx: @crate_ctxt, id: ast::def_id) ->
-       ty::ty_param_kinds_and_ty {
-        ret ty::lookup_item_type(ccx.tcx, id);
-    }
-    let f = bind getter(ccx, _);
-    ret ast_ty_to_ty(ccx.tcx, f, ast_ty);
+    ret ast_ty_to_ty(ccx.tcx, m_check, ast_ty);
 }
 
 // A wrapper around ast_ty_to_ty_crate that handles ty_infer.
@@ -402,14 +568,6 @@ fn ast_ty_to_ty_crate_infer(ccx: @crate_ctxt, &&ast_ty: @ast::ty) ->
       _ { some(ast_ty_to_ty_crate(ccx, ast_ty)) }
     }
 }
-// A wrapper around ast_ty_to_ty_infer that generates a new type variable if
-// there isn't a fixed type.
-fn ast_ty_to_ty_crate_tyvar(fcx: @fn_ctxt, &&ast_ty: @ast::ty) -> ty::t {
-    alt ast_ty_to_ty_crate_infer(fcx.ccx, ast_ty) {
-      some(ty) { ty }
-      none. { next_ty_var(fcx) }
-    }
-}
 
 
 // Functions that write types into the node type table.
@@ -428,7 +586,7 @@ fn ty(tcx: ty::ctxt, node_id: ast::node_id,
 
     // Writes a type parameter count and type pair into the node type table.
     // This function allows for the possibility of type variables, which will
-    // be rewritten later during the fixup phase.
+    // be rewritten later during the fixup mode.
     fn ty_fixup(fcx: @fn_ctxt, node_id: ast::node_id,
                 tpot: ty_param_substs_opt_and_ty) {
         inner(fcx.ccx.tcx.node_types, node_id, tpot);
@@ -459,6 +617,21 @@ fn bot_ty(tcx: ty::ctxt, node_id: ast::node_id) {
     }
 }
 
+fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param]) -> [ty::t] {
+    let tps = [];
+    let i = 0u;
+    for atp: ast::ty_param in atps {
+        tps += [ty::mk_param(tcx, i, ty_param_kind(atp))];
+        i += 1u;
+    }
+    ret tps;
+}
+
+fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] {
+    let k: [ast::kind] = [];
+    for p: ast::ty_param in tps { k += [ty_param_kind(p)]; }
+    ret k;
+}
 
 // Item collection - a pair of bootstrap passes:
 //
@@ -477,209 +650,12 @@ fn bot_ty(tcx: ty::ctxt, node_id: ast::node_id) {
 mod collect {
     type ctxt = {tcx: ty::ctxt};
 
-    fn mk_ty_params(cx: @ctxt, atps: [ast::ty_param]) -> [ty::t] {
-        let tps = [];
-        let i = 0u;
-        for atp: ast::ty_param in atps {
-            tps += [ty::mk_param(cx.tcx, i, ty_param_kind(atp))];
-            i += 1u;
-        }
-        ret tps;
-    }
-
-    fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] {
-        let k: [ast::kind] = [];
-        for p: ast::ty_param in tps { k += [ty_param_kind(p)]; }
-        ret k;
-    }
-
-    fn ty_of_fn_decl(cx: @ctxt, convert: fn@(&&@ast::ty) -> ty::t,
-                     ty_of_arg: fn@(ast::arg) -> arg, decl: ast::fn_decl,
-                     proto: ast::proto, ty_params: [ast::ty_param],
-                     def_id: option::t<ast::def_id>) ->
-       ty::ty_param_kinds_and_ty {
-        let input_tys = [];
-        for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(a)]; }
-        let output_ty = convert(decl.output);
-
-        let out_constrs = [];
-        for constr: @ast::constr in decl.constraints {
-            out_constrs += [ty::ast_constr_to_constr(cx.tcx, constr)];
-        }
-        let t_fn =
-            ty::mk_fn(cx.tcx, proto, input_tys, output_ty,
-                      decl.cf, out_constrs);
-        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
-        alt def_id { some(did) { cx.tcx.tcache.insert(did, tpt); } _ { } }
-        ret tpt;
-    }
-    fn ty_of_native_fn_decl(cx: @ctxt, convert: fn@(&&@ast::ty) -> ty::t,
-                            ty_of_arg: fn@(ast::arg) -> arg,
-                            decl: ast::fn_decl,
-                            ty_params: [ast::ty_param], def_id: ast::def_id)
-       -> ty::ty_param_kinds_and_ty {
-        let input_tys = [];
-        for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(a)]; }
-        let output_ty = convert(decl.output);
-
-        let t_fn = ty::mk_native_fn(cx.tcx, input_tys, output_ty);
-        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
-        cx.tcx.tcache.insert(def_id, tpt);
-        ret tpt;
-    }
-    fn getter(cx: @ctxt, id: ast::def_id) -> ty::ty_param_kinds_and_ty {
-        if id.crate != ast::local_crate {
-            // This is a type we need to load in from the crate reader.
-            ret csearch::get_type(cx.tcx, id);
-        }
-        let it = cx.tcx.items.find(id.node);
-        let tpt;
-        alt it {
-          some(ast_map::node_item(item)) { tpt = ty_of_item(cx, item); }
-          some(ast_map::node_native_item(native_item)) {
-            tpt = ty_of_native_item(cx, native_item);
-          }
-          _ { cx.tcx.sess.fatal("internal error " + std::int::str(id.node)); }
-        }
-        ret tpt;
-    }
-    fn ty_of_arg(cx: @ctxt, a: ast::arg) -> ty::arg {
-        let ty = ast_ty_to_ty(cx.tcx, bind getter(cx, _), a.ty);
-        {mode: default_arg_mode_for_ty(cx.tcx, a.mode, ty), ty: ty}
-    }
-    fn ty_of_method(cx: @ctxt, m: @ast::method) -> ty::method {
-        let get = bind getter(cx, _);
-        let convert = bind ast_ty_to_ty(cx.tcx, get, _);
-
-        let inputs = [];
-        for a: ast::arg in m.node.meth.decl.inputs {
-            inputs += [ty_of_arg(cx, a)];
-        }
-
-        let output = convert(m.node.meth.decl.output);
-
-        let out_constrs = [];
-        for constr: @ast::constr in m.node.meth.decl.constraints {
-            out_constrs += [ty::ast_constr_to_constr(cx.tcx, constr)];
-        }
-        ret {proto: m.node.meth.proto,
-             ident: m.node.ident,
-             inputs: inputs,
-             output: output,
-             cf: m.node.meth.decl.cf,
-             constrs: out_constrs};
-    }
-    fn ty_of_obj(cx: @ctxt, id: ast::ident, ob: ast::_obj,
-                 ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty {
-        let methods = get_obj_method_types(cx, ob);
-        let t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods));
-        t_obj = ty::rename(cx.tcx, t_obj, id);
-        ret {kinds: ty_param_kinds(ty_params), ty: t_obj};
-    }
-    fn ty_of_obj_ctor(cx: @ctxt, id: ast::ident, ob: ast::_obj,
-                      ctor_id: ast::node_id, ty_params: [ast::ty_param]) ->
-       ty::ty_param_kinds_and_ty {
-        let t_obj = ty_of_obj(cx, id, ob, ty_params);
-
-        let t_inputs: [arg] = [];
-        for f: ast::obj_field in ob.fields {
-            let g = bind getter(cx, _);
-            let t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
-            t_inputs += [{mode: ast::by_copy, ty: t_field}];
-        }
-
-        let t_fn =
-            ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal),
-                      t_inputs, t_obj.ty,
-                      ast::return_val, []);
-        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
-        cx.tcx.tcache.insert(local_def(ctor_id), tpt);
-        ret tpt;
-    }
-    fn ty_of_item(cx: @ctxt, it: @ast::item) -> ty::ty_param_kinds_and_ty {
-        let get = bind getter(cx, _);
-        let convert = bind ast_ty_to_ty(cx.tcx, get, _);
-        let no_kinds: [ast::kind] = [];
-        alt it.node {
-          ast::item_const(t, _) {
-            let typ = convert(t);
-            let tpt = {kinds: no_kinds, ty: typ};
-            cx.tcx.tcache.insert(local_def(it.id), tpt);
-            ret tpt;
-          }
-          ast::item_fn(fn_info, tps) {
-            let f = bind ty_of_arg(cx, _);
-            ret ty_of_fn_decl(cx, convert, f, fn_info.decl, fn_info.proto,
-                              tps, some(local_def(it.id)));
-          }
-          ast::item_obj(ob, tps, _) {
-            let t_obj = ty_of_obj(cx, it.ident, ob, tps);
-            cx.tcx.tcache.insert(local_def(it.id), t_obj);
-            ret t_obj;
-          }
-          ast::item_ty(t, tps) {
-            alt cx.tcx.tcache.find(local_def(it.id)) {
-              some(tpt) { ret tpt; }
-              none. { }
-            }
-            // Tell ast_ty_to_ty() that we want to perform a recursive
-            // call to resolve any named types.
-
-            let typ = convert(t);
-            let tpt = {kinds: ty_param_kinds(tps), ty: typ};
-            cx.tcx.tcache.insert(local_def(it.id), tpt);
-            ret tpt;
-          }
-          ast::item_res(f, _, tps, _) {
-            let t_arg = ty_of_arg(cx, f.decl.inputs[0]);
-            let t_res =
-                {kinds: ty_param_kinds(tps),
-                 ty: ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
-                                mk_ty_params(cx, tps))};
-            cx.tcx.tcache.insert(local_def(it.id), t_res);
-            ret t_res;
-          }
-          ast::item_tag(_, tps) {
-            // Create a new generic polytype.
-            let subtys: [ty::t] = mk_ty_params(cx, tps);
-            let t = ty::mk_tag(cx.tcx, local_def(it.id), subtys);
-            let tpt = {kinds: ty_param_kinds(tps), ty: t};
-            cx.tcx.tcache.insert(local_def(it.id), tpt);
-            ret tpt;
-          }
-          ast::item_mod(_) { fail; }
-          ast::item_native_mod(_) { fail; }
-        }
-    }
-    fn ty_of_native_item(cx: @ctxt, it: @ast::native_item)
-        -> ty::ty_param_kinds_and_ty {
-        let no_kinds: [ast::kind] = [];
-        alt it.node {
-          ast::native_item_fn(fn_decl, params) {
-            let get = bind getter(cx, _);
-            let convert = bind ast_ty_to_ty(cx.tcx, get, _);
-            let f = bind ty_of_arg(cx, _);
-            ret ty_of_native_fn_decl(cx, convert, f, fn_decl, params,
-                                     ast_util::local_def(it.id));
-          }
-          ast::native_item_ty. {
-            alt cx.tcx.tcache.find(local_def(it.id)) {
-              some(tpt) { ret tpt; }
-              none. { }
-            }
-            let t = ty::mk_native(cx.tcx, ast_util::local_def(it.id));
-            let tpt = {kinds: no_kinds, ty: t};
-            cx.tcx.tcache.insert(local_def(it.id), tpt);
-            ret tpt;
-          }
-        }
-    }
     fn get_tag_variant_types(cx: @ctxt, tag_id: ast::def_id,
                              variants: [ast::variant],
                              ty_params: [ast::ty_param]) {
         // Create a set of parameter types shared among all the variants.
 
-        let ty_param_tys: [ty::t] = mk_ty_params(cx, ty_params);
+        let ty_param_tys: [ty::t] = mk_ty_params(cx.tcx, ty_params);
         for variant: ast::variant in variants {
             // Nullary tag constructors get turned into constants; n-ary tag
             // constructors get turned into functions.
@@ -690,11 +666,9 @@ fn get_tag_variant_types(cx: @ctxt, tag_id: ast::def_id,
             } else {
                 // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
                 // should be called to resolve named types.
-
-                let f = bind getter(cx, _);
                 let args: [arg] = [];
                 for va: ast::variant_arg in variant.node.args {
-                    let arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
+                    let arg_ty = ast_ty_to_ty(cx.tcx, m_collect, va.ty);
                     args += [{mode: ast::by_copy, ty: arg_ty}];
                 }
                 let tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
@@ -709,13 +683,6 @@ fn get_tag_variant_types(cx: @ctxt, tag_id: ast::def_id,
             write::ty_only(cx.tcx, variant.node.id, result_ty);
         }
     }
-    fn get_obj_method_types(cx: @ctxt, object: ast::_obj) -> [ty::method] {
-        let meths = [];
-        for m: @ast::method in object.methods {
-            meths += [ty_of_method(cx, m)];
-        }
-        ret meths;
-    }
     fn convert(cx: @ctxt, it: @ast::item) {
         alt it.node {
           ast::item_mod(_) {
@@ -725,24 +692,23 @@ fn convert(cx: @ctxt, it: @ast::item) {
             // do nothing, as native modules have no types.
           }
           ast::item_tag(variants, ty_params) {
-            let tpt = ty_of_item(cx, it);
+            let tpt = ty_of_item(cx.tcx, m_collect, it);
             write::ty_only(cx.tcx, it.id, tpt.ty);
             get_tag_variant_types(cx, local_def(it.id), variants, ty_params);
           }
           ast::item_obj(object, ty_params, ctor_id) {
             // Now we need to call ty_of_obj_ctor(); this is the type that
             // we write into the table for this item.
-            ty_of_item(cx, it);
-
-            let tpt =
-                ty_of_obj_ctor(cx, it.ident, object, ctor_id, ty_params);
+            ty_of_item(cx.tcx, m_collect, it);
+            let tpt = ty_of_obj_ctor(cx.tcx, m_collect, it.ident, object,
+                                      ctor_id, ty_params);
             write::ty_only(cx.tcx, ctor_id, tpt.ty);
             // Write the methods into the type table.
             //
             // FIXME: Inefficient; this ends up calling
             // get_obj_method_types() twice. (The first time was above in
             // ty_of_obj().)
-            let method_types = get_obj_method_types(cx, object);
+            let method_types = ty_of_obj_methods(cx.tcx, m_collect, object);
             let i = 0u;
             while i < vec::len::<@ast::method>(object.methods) {
                 write::ty_only(cx.tcx, object.methods[i].node.id,
@@ -763,10 +729,10 @@ fn convert(cx: @ctxt, it: @ast::item) {
             }
           }
           ast::item_res(f, dtor_id, tps, ctor_id) {
-            let t_arg = ty_of_arg(cx, f.decl.inputs[0]);
+            let t_arg = ty_of_arg(cx.tcx, m_collect, f.decl.inputs[0]);
             let t_res =
                 ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
-                           mk_ty_params(cx, tps));
+                           mk_ty_params(cx.tcx, tps));
             let t_ctor =
                 ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal),
                           [{mode: ast::by_copy with t_arg}], t_res,
@@ -786,7 +752,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
             // This call populates the type cache with the converted type
             // of the item in passing. All we have to do here is to write
             // it into the node type table.
-            let tpt = ty_of_item(cx, it);
+            let tpt = ty_of_item(cx.tcx, m_collect, it);
             write::ty_only(cx.tcx, it.id, tpt.ty);
           }
         }
@@ -795,7 +761,7 @@ fn convert_native(cx: @ctxt, i: @ast::native_item) {
         // As above, this call populates the type table with the converted
         // type of the native item. We simply write it into the node type
         // table.
-        let tpt = ty_of_native_item(cx, i);
+        let tpt = ty_of_native_item(cx.tcx, m_collect, i);
         alt i.node {
           ast::native_item_ty. {
             // FIXME: Native types have no annotation. Should they? --pcw
@@ -1936,15 +1902,9 @@ fn check_binop_type_compat(fcx: @fn_ctxt, span: span, ty: ty::t,
         write::ty_only_fixup(fcx, id, result_ty);
       }
       ast::expr_fn(f) {
-        let convert = bind ast_ty_to_ty_crate_tyvar(fcx, _);
-        let ty_of_arg = lambda (a: ast::arg) -> ty::arg {
-            let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty);
-            ret {mode: default_arg_mode_for_ty(fcx.ccx.tcx, a.mode, tt),
-                 ty: tt};
-        };
         let cx = @{tcx: tcx};
-        let fty = collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl,
-                                         f.proto, [], none).ty;
+        let fty = ty_of_fn_decl(cx.tcx, m_check_tyvar(fcx), f.decl,
+                                 f.proto, [], none).ty;
 
         write::ty_only_fixup(fcx, id, fty);
 
@@ -2241,41 +2201,11 @@ fn get_node(f: spanned<field>) -> field { f.node }
         let fields: [ast::anon_obj_field] = [];
         alt ao.fields { none. { } some(v) { fields = v; } }
 
-        // FIXME: These next three functions are largely ripped off from
-        // similar ones in collect::.  Is there a better way to do this?
-        fn ty_of_arg(ccx: @crate_ctxt, a: ast::arg) -> ty::arg {
-            let ty = ast_ty_to_ty_crate(ccx, a.ty);
-            ret {mode: default_arg_mode_for_ty(ccx.tcx, a.mode, ty), ty: ty};
-        }
-
-        fn ty_of_method(ccx: @crate_ctxt, m: @ast::method) -> ty::method {
-            let convert = bind ast_ty_to_ty_crate(ccx, _);
-
-            let inputs = [];
-            for aa: ast::arg in m.node.meth.decl.inputs {
-                inputs += [ty_of_arg(ccx, aa)];
-            }
-
-            let output = convert(m.node.meth.decl.output);
-
-            let out_constrs = [];
-            for constr: @ast::constr in m.node.meth.decl.constraints {
-                out_constrs += [ty::ast_constr_to_constr(ccx.tcx, constr)];
-            }
-
-            ret {proto: m.node.meth.proto,
-                 ident: m.node.ident,
-                 inputs: inputs,
-                 output: output,
-                 cf: m.node.meth.decl.cf,
-                 constrs: out_constrs};
-        }
-
         let method_types: [ty::method] = [];
         {
             // Outer methods.
             for m: @ast::method in ao.methods {
-                method_types += [ty_of_method(fcx.ccx, m)];
+                method_types += [ty_of_method(fcx.ccx.tcx, m_check, m)];
             }
 
             // Inner methods.
@@ -2326,7 +2256,7 @@ fn filtering_fn(ccx: @crate_ctxt, m: ty::method,
                     if str::eq(om.node.ident, m.ident) {
                         // We'd better be overriding with one of the same
                         // type.  Check to make sure.
-                        let new_type = ty_of_method(ccx, om);
+                        let new_type = ty_of_method(ccx.tcx, m_check, om);
                         if new_type != m {
                             ccx.tcx.sess.span_fatal
                                 (om.span, "attempted to override method "
@@ -2517,22 +2447,20 @@ fn check_pred_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool {
               _ {
                 fcx.ccx.tcx.sess.span_err(operator.span,
                                             "Impure function as operator \
-in constraint");
+                                             in constraint");
               }
             }
             for operand: @ast::expr in operands {
                 if !ast_util::is_constraint_arg(operand) {
                     let s =
-                        "Constraint args must be \
-slot variables or literals";
+                        "Constraint args must be slot variables or literals";
                     fcx.ccx.tcx.sess.span_err(e.span, s);
                 }
             }
           }
           _ {
-            let s =
-                "In a constraint, expected the \
-constraint name to be an explicit name";
+            let s = "In a constraint, expected the \
+                     constraint name to be an explicit name";
             fcx.ccx.tcx.sess.span_err(e.span, s);
           }
         }