summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-07 12:21:08 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-08 21:17:32 +0100
commitfd465f91a89450b7daebecdde9c280a923bbe394 (patch)
tree58d345ca820a4248419a99421367a2e01257a415 /src/rustc
parent6f8fe781200e985d4d12d1b0ea4a7b338e6220a5 (diff)
downloadrust-fd465f91a89450b7daebecdde9c280a923bbe394.tar.gz
rust-fd465f91a89450b7daebecdde9c280a923bbe394.zip
Drop collect_items pass, create decls on demand
This solves a problem with inlined functions that have inner functions.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/driver/driver.rs2
-rw-r--r--src/rustc/metadata/astencode.rs2
-rw-r--r--src/rustc/metadata/encoder.rs27
-rw-r--r--src/rustc/metadata/reachable.rs2
-rw-r--r--src/rustc/middle/ast_map.rs47
-rw-r--r--src/rustc/middle/trans/base.rs419
-rw-r--r--src/rustc/middle/trans/common.rs8
-rw-r--r--src/rustc/middle/trans/debuginfo.rs2
-rw-r--r--src/rustc/middle/trans/impl.rs25
-rw-r--r--src/rustc/middle/trans/native.rs67
-rw-r--r--src/rustc/middle/ty.rs7
-rw-r--r--src/rustc/middle/typeck.rs8
12 files changed, 290 insertions, 326 deletions
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index fe05a4422ed..4f037511418 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -131,7 +131,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
 
     let ast_map =
         time(time_passes, "ast indexing",
-             bind middle::ast_map::map_crate(*crate));
+             bind middle::ast_map::map_crate(sess, *crate));
     time(time_passes, "external crate/lib resolution",
          bind creader::read_crates(sess, *crate));
     let {def_map, exp_map, impl_map} =
diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs
index d7215fbfcab..8e6d7a0a526 100644
--- a/src/rustc/metadata/astencode.rs
+++ b/src/rustc/metadata/astencode.rs
@@ -89,7 +89,7 @@ fn decode_inlined_item(cdata: cstore::crate_metadata,
                     to_id_range: to_id_range};
         let raw_ii = decode_ast(ast_doc);
         let ii = renumber_ast(xcx, raw_ii);
-        ast_map::map_decoded_item(dcx.tcx.items, path, ii);
+        ast_map::map_decoded_item(tcx.sess, dcx.tcx.items, path, ii);
         #debug["Fn named: %s", ii.ident()];
         decode_side_tables(xcx, ast_doc);
         #debug["< Decoded inlined fn: %s::%s",
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index c2c0cbc9150..0b24b3325d9 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -328,7 +328,7 @@ fn purity_fn_family(p: purity) -> char {
 }
 
 fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
-                        &index: [entry<int>], path: ast_map::path) {
+                        &index: [entry<int>], path: ast_map::path) -> bool {
 
     fn should_inline(attrs: [attribute]) -> bool {
         alt attr::find_inline_attr(attrs) {
@@ -342,7 +342,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
       item_enum(_, _) | item_res(_, _, _, _, _) { true }
       _ { false }
     };
-    if !must_write && !ecx.reachable.contains_key(item.id) { ret; }
+    if !must_write && !ecx.reachable.contains_key(item.id) { ret false; }
 
     alt item.node {
       item_const(_, _) {
@@ -494,11 +494,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         ebml_w.end_tag();
       }
     }
+    ret true;
 }
 
 fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
-                               nitem: @native_item, path: ast_map::path) {
-    if !ecx.reachable.contains_key(nitem.id) { ret; }
+                               nitem: @native_item, path: ast_map::path)
+    -> bool {
+    if !ecx.reachable.contains_key(nitem.id) { ret false; }
     ebml_w.start_tag(tag_items_data_item);
     alt nitem.node {
       native_item_fn(fn_decl, tps) {
@@ -511,6 +513,7 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
       }
     }
     ebml_w.end_tag();
+    ret true;
 }
 
 fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
@@ -520,17 +523,17 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
     index += [{val: crate_node_id, pos: ebml_w.writer.tell()}];
     encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, [], "");
     ecx.ccx.tcx.items.items {|key, val|
-        alt val {
+        let where = ebml_w.writer.tell();
+        let written = alt val {
           middle::ast_map::node_item(i, path) {
-            index += [{val: key, pos: ebml_w.writer.tell()}];
-            encode_info_for_item(ecx, ebml_w, i, index, *path);
+            encode_info_for_item(ecx, ebml_w, i, index, *path)
           }
-          middle::ast_map::node_native_item(i, path) {
-            index += [{val: key, pos: ebml_w.writer.tell()}];
-            encode_info_for_native_item(ecx, ebml_w, i, *path);
+          middle::ast_map::node_native_item(i, _, path) {
+            encode_info_for_native_item(ecx, ebml_w, i, *path)
           }
-          _ { }
-        }
+          _ { false }
+        };
+        if written { index += [{val: key, pos: where}]; }
     };
     ebml_w.end_tag();
     ret index;
diff --git a/src/rustc/metadata/reachable.rs b/src/rustc/metadata/reachable.rs
index dad1f9b7039..b66ac037bde 100644
--- a/src/rustc/metadata/reachable.rs
+++ b/src/rustc/metadata/reachable.rs
@@ -58,7 +58,7 @@ fn traverse_def_id(cx: ctx, did: def_id) {
     alt cx.ccx.tcx.items.get(did.node) {
       ast_map::node_item(item, _) { traverse_public_item(cx, item); }
       ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
-      ast_map::node_native_item(item, _) { cx.rmap.insert(item.id, ()); }
+      ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.id, ()); }
       ast_map::node_variant(v, _, _) { cx.rmap.insert(v.node.id, ()); }
       _ {}
     }
diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs
index c39686b0d30..4240c0e5092 100644
--- a/src/rustc/middle/ast_map.rs
+++ b/src/rustc/middle/ast_map.rs
@@ -4,6 +4,8 @@ import syntax::ast::*;
 import syntax::ast_util;
 import syntax::ast_util::inlined_item_methods;
 import syntax::{visit, codemap};
+import driver::session::session;
+import front::attr;
 
 enum path_elt { path_mod(str), path_name(str) }
 type path = [path_elt];
@@ -24,20 +26,21 @@ fn path_to_str(p: path) -> str {
 
 enum ast_node {
     node_item(@item, @path),
-    node_native_item(@native_item, @path),
+    node_native_item(@native_item, native_abi, @path),
     node_method(@method, def_id /* impl did */, @path /* path to the impl */),
-    node_variant(variant, def_id, @path),
+    node_variant(variant, @item, @path),
     node_expr(@expr),
     node_export(@view_path, @path),
     // Locals are numbered, because the alias analysis needs to know in which
     // order they are introduced.
     node_arg(arg, uint),
     node_local(uint),
-    node_res_ctor(@item),
+    node_ctor(@item),
 }
 
 type map = std::map::hashmap<node_id, ast_node>;
-type ctx = {map: map, mutable path: path, mutable local_id: uint};
+type ctx = {map: map, mutable path: path,
+            mutable local_id: uint, sess: session};
 type vt = visit::vt<ctx>;
 
 fn extend(cx: ctx, elt: str) -> @path {
@@ -47,7 +50,6 @@ fn extend(cx: ctx, elt: str) -> @path {
 fn mk_ast_map_visitor() -> vt {
     ret visit::mk_vt(@{
         visit_item: map_item,
-        visit_native_item: map_native_item,
         visit_expr: map_expr,
         visit_fn: map_fn,
         visit_local: map_local,
@@ -57,10 +59,11 @@ fn mk_ast_map_visitor() -> vt {
     });
 }
 
-fn map_crate(c: crate) -> map {
+fn map_crate(sess: session, c: crate) -> map {
     let cx = {map: std::map::new_int_hash(),
               mutable path: [],
-              mutable local_id: 0u};
+              mutable local_id: 0u,
+              sess: sess};
     visit::visit_crate(c, cx, mk_ast_map_visitor());
     ret cx.map;
 }
@@ -68,7 +71,7 @@ fn map_crate(c: crate) -> map {
 // Used for items loaded from external crate that are being inlined into this
 // crate.  The `path` should be the path to the item but should not include
 // the item itself.
-fn map_decoded_item(map: map, path: path, ii: inlined_item) {
+fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) {
     // I believe it is ok for the local IDs of inlined items from other crates
     // to overlap with the local ids from this crate, so just generate the ids
     // starting from 0.  (In particular, I think these ids are only used in
@@ -77,7 +80,8 @@ fn map_decoded_item(map: map, path: path, ii: inlined_item) {
     // variables that are simultaneously in scope).
     let cx = {map: map,
               mutable path: path,
-              mutable local_id: 0u};
+              mutable local_id: 0u,
+              sess: sess};
     let v = mk_ast_map_visitor();
 
     // methods get added to the AST map when their impl is visited.  Since we
@@ -86,7 +90,7 @@ fn map_decoded_item(map: map, path: path, ii: inlined_item) {
     alt ii {
       ii_item(i) { /* fallthrough */ }
       ii_method(impl_did, m) {
-        map_method(impl_did, @vec::init(path), m, cx);
+        map_method(impl_did, @path, m, cx);
       }
     }
 
@@ -137,19 +141,31 @@ fn map_item(i: @item, cx: ctx, v: vt) {
       item_impl(_, _, _, ms) {
         let impl_did = ast_util::local_def(i.id);
         for m in ms {
-            map_method(impl_did, item_path, m, cx);
+            map_method(impl_did, extend(cx, i.ident), m, cx);
         }
       }
       item_res(_, _, _, dtor_id, ctor_id) {
-        cx.map.insert(ctor_id, node_res_ctor(i));
+        cx.map.insert(ctor_id, node_ctor(i));
         cx.map.insert(dtor_id, node_item(i, item_path));
       }
       item_enum(vs, _) {
         for v in vs {
             cx.map.insert(v.node.id, node_variant(
-                v, ast_util::local_def(i.id), extend(cx, i.ident)));
+                v, i, extend(cx, i.ident)));
         }
       }
+      item_native_mod(nm) {
+        let abi = alt attr::native_abi(i.attrs) {
+          either::left(msg) { cx.sess.span_fatal(i.span, msg); }
+          either::right(abi) { abi }
+        };
+        for nitem in nm.items {
+            cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
+        }
+      }
+      item_class(_, _, ctor) {
+        cx.map.insert(ctor.node.id, node_ctor(i));
+      }
       _ { }
     }
     alt i.node {
@@ -179,11 +195,6 @@ fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
     }
 }
 
-fn map_native_item(i: @native_item, cx: ctx, v: vt) {
-    cx.map.insert(i.id, node_native_item(i, @cx.path));
-    visit::visit_native_item(i, cx, v);
-}
-
 fn map_expr(ex: @expr, cx: ctx, v: vt) {
     cx.map.insert(ex.id, node_expr(ex));
     visit::visit_expr(ex, cx, v);
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 74a9c6111fa..6f53c56e32c 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2111,7 +2111,7 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
       ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
       ast_map::node_method(m, _, pt) { (pt, m.ident) }
       // We can't monomorphize native functions
-      ast_map::node_native_item(_, _) { ret none; }
+      ast_map::node_native_item(_, _, _) { ret none; }
       _ { fail "unexpected node type"; }
     };
     let pt = *pt + [path_name(ccx.names(name))];
@@ -2128,11 +2128,11 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
       ast_map::node_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
         trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
       }
-      ast_map::node_variant(v, enum_id, _) {
-        let tvs = ty::enum_variants(ccx.tcx, enum_id);
+      ast_map::node_variant(v, enum_item, _) {
+        let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
         let this_tv = option::get(vec::find(*tvs, {|tv|
             tv.id.node == fn_id.node}));
-        trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val,
+        trans_enum_variant(ccx, enum_item.id, v, this_tv.disr_val,
                            (*tvs).len() == 1u, [], psubsts, lldecl);
       }
       ast_map::node_method(mth, impl_def_id, _) {
@@ -2164,7 +2164,6 @@ fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id)
                    ty::item_path_str(ccx.tcx, fn_id),
                    item.id];
             ccx.external.insert(fn_id, some(item.id));
-            collect_item(ccx, @mutable none, item);
             trans_item(ccx, *item);
             local_def(item.id)
           }
@@ -2176,11 +2175,7 @@ fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id)
                    mth.id];
             ccx.external.insert(fn_id, some(mth.id));
             compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path|
-                let mth_ty = ty::node_id_to_type(ccx.tcx, mth.id);
-                let llfn = register_fn_full(ccx, mth.span, path,
-                                            "impl_method", bounds,
-                                            mth.id, mth_ty);
-                set_inline_hint_if_appr(mth.attrs, llfn);
+                let llfn = get_item_val(ccx, mth.id);
                 trans_fn(ccx, path, mth.decl, mth.body,
                          llfn, impl_self(ty), bounds,
                          none, mth.id, none);
@@ -2243,8 +2238,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
 
     let val = if fn_id.crate == ast::local_crate {
         // Internal reference.
-        assert (ccx.item_ids.contains_key(fn_id.node));
-        ccx.item_ids.get(fn_id.node)
+        get_item_val(ccx, fn_id.node)
     } else {
         // External reference.
         trans_external_path(bcx, fn_id, tpt)
@@ -2375,8 +2369,7 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
       }
       ast::def_const(did) {
         if did.crate == ast::local_crate {
-            assert (ccx.consts.contains_key(did.node));
-            ret lval_no_env(cx, ccx.consts.get(did.node), owned);
+            ret lval_no_env(cx, get_item_val(ccx, did.node), owned);
         } else {
             let tp = node_id_type(cx, id);
             let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
@@ -4323,19 +4316,14 @@ fn trans_const_expr(cx: crate_ctxt, e: @ast::expr) -> ValueRef {
     }
 }
 
-fn trans_const(cx: crate_ctxt, e: @ast::expr, id: ast::node_id) {
-    let v = trans_const_expr(cx, e);
+fn trans_const(ccx: crate_ctxt, e: @ast::expr, id: ast::node_id) {
+    let v = trans_const_expr(ccx, e);
 
     // The scalars come back as 1st class LLVM vals
     // which we have to stick into global constants.
-
-    alt cx.consts.find(id) {
-      some(g) {
-        llvm::LLVMSetInitializer(g, v);
-        llvm::LLVMSetGlobalConstant(g, True);
-      }
-      _ { cx.sess.span_bug(e.span, "unbound const in trans_const"); }
-    }
+    let g = get_item_val(ccx, id);
+    llvm::LLVMSetInitializer(g, v);
+    llvm::LLVMSetGlobalConstant(g, True);
 }
 
 fn trans_item(ccx: crate_ctxt, item: ast::item) {
@@ -4344,15 +4332,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
     };
     alt item.node {
       ast::item_fn(decl, tps, body) {
-        let llfndecl = alt ccx.item_ids.find(item.id) {
-          some(llfndecl) { llfndecl }
-          _ {
-            ccx.sess.span_bug(
-                item.span,
-                #fmt["unbound function item %s in trans_item",
-                     ast_map::path_to_str(*path)]);
-          }
-        };
+        let llfndecl = get_item_val(ccx, item.id);
         if decl.purity != ast::crust_fn  {
             trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
                      llfndecl, no_self, param_bounds(ccx, tps),
@@ -4366,21 +4346,15 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
         impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
       }
       ast::item_res(decl, tps, body, dtor_id, ctor_id) {
-        let llctor_decl = ccx.item_ids.get(ctor_id);
+        let llctor_decl = get_item_val(ccx, ctor_id);
         trans_res_ctor(ccx, *path, decl, ctor_id,
                        param_bounds(ccx, tps), none, llctor_decl);
 
         // Create a function for the destructor
-        alt ccx.item_ids.find(item.id) {
-          some(lldtor_decl) {
-            trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
-                     lldtor_decl, no_self, param_bounds(ccx, tps),
-                     none, dtor_id, none);
-          }
-          _ {
-            ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
-          }
-        }
+        let lldtor_decl = get_item_val(ccx, item.id);
+        trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
+                 lldtor_decl, no_self, param_bounds(ccx, tps),
+                 none, dtor_id, none);
       }
       ast::item_mod(m) {
         trans_mod(ccx, m);
@@ -4393,7 +4367,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
             if variant.node.args.len() > 0u {
                 trans_enum_variant(ccx, item.id, variant,
                                    vi[i].disr_val, degen, tps,
-                                   none, ccx.item_ids.get(variant.node.id));
+                                   none, get_item_val(ccx, variant.node.id));
             }
             i += 1;
         }
@@ -4407,81 +4381,74 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
         native::trans_native_mod(ccx, native_mod, abi);
       }
       ast::item_class(tps, items, ctor) {
-          alt ccx.item_ids.find(ctor.node.id) {
-             some(llctor_decl) {
-             // Translate the ctor
-             // First, add a preamble that
-             // generates a new name, obj:
-             // let obj = { ... } (uninit record fields)
-                 let sess = ccx.sess;
-                 let rslt_path_ = {global: false,
-                                   idents: ["obj"],
-                                   types: []}; // ??
-                 let rslt_path = @{node: rslt_path_,
-                                  span: ctor.node.body.span};
-                 let rslt_id : ast::node_id = sess.next_node_id();
-                 let rslt_pat : @ast::pat =
-                     @{id: sess.next_node_id(),
-                       node: ast::pat_ident(rslt_path, none),
-                       span: ctor.node.body.span};
-                 // Set up obj's type
-                 let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer,
-                                    span: ctor.node.body.span};
-                 // kludgy
-                 let ty_args = [], i = 0u;
-                 for tp in tps {
-                   ty_args += [ty::mk_param(ccx.tcx, i,
-                                            local_def(tps[i].id))];
-                 }
-                 let rslt_ty =  ty::mk_class(ccx.tcx,
-                                                  local_def(item.id),
-                                             ty_args);
-                 // Set up a local for obj
-                 let rslt_loc_ : ast::local_ = {is_mutbl: true,
-                                  ty: rslt_ast_ty, // ???
-                                  pat: rslt_pat,
-                                  init: none::<ast::initializer>,
-                                  id: rslt_id};
-                 // Register a type for obj
-                 smallintmap::insert(*ccx.tcx.node_types,
-                                     rslt_loc_.id as uint, rslt_ty);
-                 // Create the decl statement that initializers obj
-                 let rslt_loc : @ast::local =
-                     @{node: rslt_loc_, span: ctor.node.body.span};
-                 let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]);
-                 let rslt_decl : @ast::decl
-                     = @{node: rslt_decl_, span: ctor.node.body.span};
-                 let prologue : @ast::stmt = @{node: ast::stmt_decl(rslt_decl,
-                                                     sess.next_node_id()),
-                                              span: ctor.node.body.span};
-                 let rslt_node_id = sess.next_node_id();
-                 ccx.tcx.def_map.insert(rslt_node_id,
-                          ast::def_local(rslt_loc_.id, true));
-                 // And give the statement a type
-                 smallintmap::insert(*ccx.tcx.node_types,
-                                     rslt_node_id as uint, rslt_ty);
-                 // The result expression of the constructor is now a
-                 // reference to obj
-                 let rslt_expr : @ast::expr =
-                     @{id: rslt_node_id,
-                       node: ast::expr_path(rslt_path),
-                       span: ctor.node.body.span};
-                 let ctor_body_new : ast::blk_ = {stmts: [prologue]
-                                      + ctor.node.body.node.stmts,
-                                       expr: some(rslt_expr)
-                                     with ctor.node.body.node};
-                 let ctor_body__ : ast::blk = {node: ctor_body_new
-                                                with ctor.node.body};
-             trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
-                      ctor_body__, llctor_decl, no_self,
-                      param_bounds(ccx, tps), none, ctor.node.id,
-                      some(rslt_expr));
-             // TODO: translate methods!
-             }
-             _ {
-               ccx.sess.span_bug(item.span, "unbound ctor in trans_item");
-             }
-          }
+        let llctor_decl = get_item_val(ccx, ctor.node.id);
+        // Translate the ctor
+        // First, add a preamble that
+        // generates a new name, obj:
+        // let obj = { ... } (uninit record fields)
+        let rslt_path_ = {global: false,
+                          idents: ["obj"],
+                          types: []}; // ??
+        let rslt_path = @{node: rslt_path_,
+                          span: ctor.node.body.span};
+        let rslt_id : ast::node_id = ccx.sess.next_node_id();
+        let rslt_pat : @ast::pat =
+            @{id: ccx.sess.next_node_id(),
+              node: ast::pat_ident(rslt_path, none),
+              span: ctor.node.body.span};
+        // Set up obj's type
+        let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer,
+                                       span: ctor.node.body.span};
+        // kludgy
+        let ty_args = [], i = 0u;
+        for tp in tps {
+            ty_args += [ty::mk_param(ccx.tcx, i,
+                                     local_def(tps[i].id))];
+        }
+        let rslt_ty =  ty::mk_class(ccx.tcx,
+                                    local_def(item.id),
+                                    ty_args);
+        // Set up a local for obj
+        let rslt_loc_ : ast::local_ = {is_mutbl: true,
+                                       ty: rslt_ast_ty, // ???
+                                       pat: rslt_pat,
+                                       init: none::<ast::initializer>,
+                                       id: rslt_id};
+        // Register a type for obj
+        smallintmap::insert(*ccx.tcx.node_types,
+                            rslt_loc_.id as uint, rslt_ty);
+        // Create the decl statement that initializers obj
+        let rslt_loc : @ast::local =
+            @{node: rslt_loc_, span: ctor.node.body.span};
+        let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]);
+        let rslt_decl : @ast::decl
+            = @{node: rslt_decl_, span: ctor.node.body.span};
+        let prologue = @{node: ast::stmt_decl(rslt_decl,
+                                              ccx.sess.next_node_id()),
+                         span: ctor.node.body.span};
+        let rslt_node_id = ccx.sess.next_node_id();
+        ccx.tcx.def_map.insert(rslt_node_id,
+                               ast::def_local(rslt_loc_.id, true));
+        // And give the statement a type
+        smallintmap::insert(*ccx.tcx.node_types,
+                            rslt_node_id as uint, rslt_ty);
+        // The result expression of the constructor is now a
+        // reference to obj
+        let rslt_expr : @ast::expr =
+            @{id: rslt_node_id,
+              node: ast::expr_path(rslt_path),
+              span: ctor.node.body.span};
+        let ctor_body_new : ast::blk_ = {stmts: [prologue]
+                                             + ctor.node.body.node.stmts,
+                                         expr: some(rslt_expr)
+                                         with ctor.node.body.node};
+        let ctor_body__ : ast::blk = {node: ctor_body_new
+                                      with ctor.node.body};
+        trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
+                 ctor_body__, llctor_decl, no_self,
+                 param_bounds(ccx, tps), none, ctor.node.id,
+                 some(rslt_expr));
+        // TODO: translate methods!
       }
       _ {/* fall through */ }
     }
@@ -4538,7 +4505,6 @@ fn register_fn_fuller(ccx: crate_ctxt, sp: span, path: path, _flav: str,
                       cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
     let ps: str = mangle_exported_name(ccx, path, node_type);
     let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
-    ccx.item_ids.insert(node_id, llfn);
     ccx.item_symbols.insert(node_id, ps);
 
     #debug["register_fn_fuller created fn %s for item %d with path %s",
@@ -4649,145 +4615,96 @@ fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
     Store(bcx, llenvblobptr, env_cell);
 }
 
-fn collect_native_item(ccx: crate_ctxt,
-                       abi: @mutable option<ast::native_abi>,
-                       i: @ast::native_item) {
-    alt i.node {
-      ast::native_item_fn(_, tps) {
-        let id = i.id;
-        let node_type = ty::node_id_to_type(ccx.tcx, id);
-        let fn_abi =
-            alt attr::get_meta_item_value_str_by_name(i.attrs, "abi") {
-            option::none {
-                // if abi isn't specified for this function, inherit from
-                  // its enclosing native module
-                  option::get(*abi)
-              }
-                _ {
-                    alt attr::native_abi(i.attrs) {
-                      either::right(abi_) { abi_ }
-                      either::left(msg) { ccx.sess.span_fatal(i.span, msg) }
-                    }
-                }
-            };
-        alt fn_abi {
-          ast::native_abi_rust_intrinsic {
-            // For intrinsics: link the function directly to the intrinsic
-            // function itself.
-            let fn_type = type_of_fn_from_ty(
-                ccx, node_type, param_bounds(ccx, tps));
-            let ri_name = "rust_intrinsic_" + native::link_name(i);
-            let llnativefn = get_extern_fn(
-                ccx.externs, ccx.llmod, ri_name,
-                lib::llvm::CCallConv, fn_type);
-            ccx.item_ids.insert(id, llnativefn);
-            ccx.item_symbols.insert(id, ri_name);
-          }
-
-          ast::native_abi_cdecl | ast::native_abi_stdcall {
-            // For true external functions: create a rust wrapper
-            // and link to that.  The rust wrapper will handle
-            // switching to the C stack.
-            let path = *alt check ccx.tcx.items.get(i.id) {
-              ast_map::node_native_item(_, p) { p }
-            } + [path_name(i.ident)];
-            register_fn(ccx, i.span, path, "native fn", tps, i.id);
-          }
-        }
-      }
-      _ { }
-    }
-}
-
 fn item_path(ccx: crate_ctxt, i: @ast::item) -> path {
     *alt check ccx.tcx.items.get(i.id) {
       ast_map::node_item(_, p) { p }
     } + [path_name(i.ident)]
 }
 
-fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
-                i: @ast::item) {
-    let my_path = item_path(ccx, i);
-    alt i.node {
-      ast::item_const(_, _) {
-        let typ = ty::node_id_to_type(ccx.tcx, i.id);
-        let s = mangle_exported_name(ccx, my_path, typ);
-        let g = str::as_buf(s, {|buf|
-            llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
-        });
-        ccx.item_symbols.insert(i.id, s);
-        ccx.consts.insert(i.id, g);
-      }
-      ast::item_native_mod(native_mod) {
-        // Propagate the native ABI down to collect_native_item(),
-        alt attr::native_abi(i.attrs) {
-          either::left(msg) { ccx.sess.span_fatal(i.span, msg); }
-          either::right(abi_) { *abi = option::some(abi_); }
-        }
-      }
-      ast::item_fn(decl, tps, _) {
-        let llfn = if decl.purity != ast::crust_fn {
-            register_fn(ccx, i.span, my_path, "fn", tps, i.id)
-        } else {
-            native::register_crust_fn(ccx, i.span, my_path, i.id)
-        };
-
-        set_inline_hint_if_appr(i.attrs, llfn);
-      }
-      ast::item_impl(tps, _, _, methods) {
-        let path = my_path + [path_name(int::str(i.id))];
-        for m in methods {
-            let llm  = register_fn(ccx, i.span,
-                                   path + [path_name(m.ident)],
-                                   "impl_method", tps + m.tps, m.id);
-            set_inline_hint_if_appr(m.attrs, llm);
-        }
-      }
-      ast::item_res(_, tps, _, dtor_id, ctor_id) {
-        let llctor = register_fn(ccx, i.span, my_path, "res_ctor", tps,
-                                 ctor_id);
-
-        // Note that the destructor is associated with the item's id, not
-        // the dtor_id. This is a bit counter-intuitive, but simplifies
-        // ty_res, which would have to carry around two def_ids otherwise
-        // -- one to identify the type, and one to find the dtor symbol.
-        let t = ty::node_id_to_type(ccx.tcx, dtor_id);
-        let lldtor = register_fn_full(ccx, i.span, my_path +
-                                      [path_name("dtor")], "res_dtor",
-                                      param_bounds(ccx, tps), i.id, t);
-
-        // give hints that resource ctors/dtors ought to be inlined
-        set_inline_hint(llctor);
-        set_inline_hint(lldtor);
-      }
-      ast::item_enum(variants, tps) {
-        for variant in variants {
-            if variant.node.args.len() != 0u {
-                register_fn(ccx, i.span,
-                            my_path + [path_name(variant.node.name)],
-                            "enum", tps, variant.node.id);
+fn get_item_val(ccx: crate_ctxt, id: ast::node_id) -> ValueRef {
+    alt ccx.item_vals.find(id) {
+      some(v) { v }
+      none {
+        let val = alt check ccx.tcx.items.get(id) {
+          ast_map::node_item(i, pth) {
+            let my_path = *pth + [path_name(i.ident)];
+            alt check i.node {
+              ast::item_const(_, _) {
+                let typ = ty::node_id_to_type(ccx.tcx, i.id);
+                let s = mangle_exported_name(ccx, my_path, typ);
+                let g = str::as_buf(s, {|buf|
+                    llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
+                });
+                ccx.item_symbols.insert(i.id, s);
+                g
+              }
+              ast::item_fn(decl, tps, _) {
+                let llfn = if decl.purity != ast::crust_fn {
+                    register_fn(ccx, i.span, my_path, "fn", tps, i.id)
+                } else {
+                    native::register_crust_fn(ccx, i.span, my_path, i.id)
+                };
+                set_inline_hint_if_appr(i.attrs, llfn);
+                llfn
+              }
+              ast::item_res(_, tps, _, dtor_id, _) {
+                // Note that the destructor is associated with the item's id,
+                // not the dtor_id. This is a bit counter-intuitive, but
+                // simplifies ty_res, which would have to carry around two
+                // def_ids otherwise -- one to identify the type, and one to
+                // find the dtor symbol.
+                let t = ty::node_id_to_type(ccx.tcx, dtor_id);
+                register_fn_full(ccx, i.span, my_path + [path_name("dtor")],
+                                 "res_dtor", param_bounds(ccx, tps), i.id, t)
+              }
             }
-        }
-      }
-      ast::item_class(tps,_,ctor) {
-          // Register the ctor
-          let t = ty::node_id_to_type(ccx.tcx, ctor.node.id);
-          register_fn_full(ccx, i.span, my_path, "ctor",
-                           param_bounds(ccx, tps), ctor.node.id, t);
+          }
+          ast_map::node_method(m, impl_id, pth) {
+            let mty = ty::node_id_to_type(ccx.tcx, id);
+            let impl_tps = *ty::lookup_item_type(ccx.tcx, impl_id).bounds;
+            let pth = *pth + [path_name(int::str(impl_id.node)),
+                              path_name(m.ident)];
+            let llfn = register_fn_full(ccx, m.span, pth, "impl_method",
+                                        impl_tps + param_bounds(ccx, m.tps),
+                                        id, mty);
+            set_inline_hint_if_appr(m.attrs, llfn);
+            llfn
+          }
+          ast_map::node_native_item(ni, _, pth) {
+            native::decl_native_fn(ccx, ni, *pth + [path_name(ni.ident)])
+          }
+          ast_map::node_ctor(i) {
+            alt check i.node {
+              ast::item_res(_, tps, _, _, _) {
+                let my_path = item_path(ccx, i);
+                let llctor = register_fn(ccx, i.span, my_path, "res_ctor",
+                                         tps, id);
+                set_inline_hint(llctor);
+                llctor
+              }
+              ast::item_class(tps, _, ctor) {
+                register_fn(ccx, i.span, item_path(ccx, i), "ctor", tps, id)
+              }
+            }
+          }
+          ast_map::node_variant(v, enm, pth) {
+            assert v.node.args.len() != 0u;
+            let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];
+            let llfn = alt check enm.node {
+              ast::item_enum(_, tps) {
+                register_fn(ccx, v.span, pth, "enum", tps, id)
+              }
+            };
+            set_inline_hint(llfn);
+            llfn
+          }
+        };
+        ccx.item_vals.insert(id, val);
+        val
       }
-      _ { }
     }
 }
 
-fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
-    let abi = @mutable none;
-    visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
-        visit_native_item: bind collect_native_item(ccx, abi, _),
-        visit_item: bind collect_item(ccx, abi, _)
-        with *visit::default_simple_visitor()
-    }));
-}
-
 // The constant translation pass.
 fn trans_constant(ccx: crate_ctxt, it: @ast::item) {
     alt it.node {
@@ -5043,7 +4960,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           tn: tn,
           externs: new_str_hash::<ValueRef>(),
           intrinsics: intrinsics,
-          item_ids: new_int_hash::<ValueRef>(),
+          item_vals: new_int_hash::<ValueRef>(),
           exp_map: emap,
           item_symbols: new_int_hash::<str>(),
           mutable main_fn: none::<ValueRef>,
@@ -5051,7 +4968,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           enum_sizes: ty::new_ty_hash(),
           discrims: ast_util::new_def_id_hash::<ValueRef>(),
           discrim_symbols: new_int_hash::<str>(),
-          consts: new_int_hash::<ValueRef>(),
           tydescs: ty::new_ty_hash(),
           dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
           external: util::common::new_def_hash(),
@@ -5084,7 +5000,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           crate_map: crate_map,
           dbg_cx: dbg_cx,
           mutable do_not_commit_warning_issued: false};
-    collect_items(ccx, crate);
     trans_constants(ccx, crate);
     trans_mod(ccx, crate.node.module);
     fill_crate_map(ccx, crate_map);
diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 5bb2dfb885f..82f826d9ee8 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -81,7 +81,7 @@ type crate_ctxt = @{
      tn: type_names,
      externs: hashmap<str, ValueRef>,
      intrinsics: hashmap<str, ValueRef>,
-     item_ids: hashmap<ast::node_id, ValueRef>,
+     item_vals: hashmap<ast::node_id, ValueRef>,
      exp_map: resolve::exp_map,
      item_symbols: hashmap<ast::node_id, str>,
      mutable main_fn: option<ValueRef>,
@@ -89,7 +89,6 @@ type crate_ctxt = @{
      enum_sizes: hashmap<ty::t, uint>,
      discrims: hashmap<ast::def_id, ValueRef>,
      discrim_symbols: hashmap<ast::node_id, str>,
-     consts: hashmap<ast::node_id, ValueRef>,
      tydescs: hashmap<ty::t, @tydesc_info>,
      dicts: hashmap<dict_id, ValueRef>,
      // Track mapping of external ids to local items imported for inlining
@@ -300,10 +299,7 @@ fn revoke_clean(cx: block, val: ValueRef) {
 fn get_res_dtor(ccx: crate_ctxt, did: ast::def_id, inner_t: ty::t)
    -> ValueRef {
     if did.crate == ast::local_crate {
-        alt ccx.item_ids.find(did.node) {
-          some(x) { ret x; }
-          _ { ccx.sess.bug("get_res_dtor: can't find resource dtor!"); }
-        }
+        ret base::get_item_val(ccx, did.node);
     }
 
     let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs
index 47a3d2e5716..fd3f94625d1 100644
--- a/src/rustc/middle/trans/debuginfo.rs
+++ b/src/rustc/middle/trans/debuginfo.rs
@@ -793,7 +793,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
       ast_map::node_method(method, _, _) {
           (method.ident, method.decl.output, method.id)
       }
-      ast_map::node_res_ctor(item) {
+      ast_map::node_ctor(item) {
         alt item.node {
             ast::item_res(decl, _, _, _, ctor_id) {
               (item.ident, decl.output, ctor_id)
diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs
index 86522ba9934..16cc55a6f94 100644
--- a/src/rustc/middle/trans/impl.rs
+++ b/src/rustc/middle/trans/impl.rs
@@ -48,17 +48,11 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident,
               tps: [ast::ty_param]) {
     let sub_path = path + [path_name(name)];
     for m in methods {
-        alt ccx.item_ids.find(m.id) {
-          some(llfn) {
-            let m_bounds = param_bounds(ccx, tps + m.tps);
-            trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
-                     llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
-                     m_bounds, none, m.id, none);
-          }
-          _ {
-            ccx.sess.bug("unbound id in trans_impl");
-          }
-        }
+        let llfn = get_item_val(ccx, m.id);
+        let m_bounds = param_bounds(ccx, tps + m.tps);
+        trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
+                 llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
+                 m_bounds, none, m.id, none);
     }
 }
 
@@ -222,7 +216,7 @@ fn trans_vtable(ccx: crate_ctxt, id: ast::node_id, name: str,
     });
     llvm::LLVMSetInitializer(vt_gvar, tbl);
     llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
-    ccx.item_ids.insert(id, vt_gvar);
+    ccx.item_vals.insert(id, vt_gvar);
     ccx.item_symbols.insert(id, name);
 }
 
@@ -343,13 +337,12 @@ fn trans_impl_vtable(ccx: crate_ctxt, pt: path,
     let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im|
         alt vec::find(ms, {|m| m.ident == im.ident}) {
           some(m) {
-            let target = ccx.item_ids.get(m.id);
             trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)],
-                               extra_tps, target)
+                               extra_tps, get_item_val(ccx, m.id))
           }
           _ {
             ccx.sess.span_bug(it.span, "no matching method \
-               in trans_impl_vtable");
+                                        in trans_impl_vtable");
           }
         }
     });
@@ -491,7 +484,7 @@ fn get_dict_ptrs(bcx: block, origin: typeck::dict_origin)
     let ccx = bcx.ccx();
     fn get_vtable(ccx: crate_ctxt, did: ast::def_id) -> ValueRef {
         if did.crate == ast::local_crate {
-            ccx.item_ids.get(did.node)
+            get_item_val(ccx, did.node)
         } else {
             let name = csearch::get_symbol(ccx.sess.cstore, did);
             get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index dff2a207cd0..ba2c60a6bc9 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -11,7 +11,8 @@ import base::*;
 import type_of::*;
 import std::map::hashmap;
 
-export link_name, trans_native_mod, register_crust_fn, trans_crust_fn;
+export link_name, trans_native_mod, register_crust_fn, trans_crust_fn,
+       decl_native_fn;
 
 fn link_name(i: @ast::native_item) -> str {
     alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") {
@@ -238,7 +239,10 @@ fn trans_native_mod(ccx: crate_ctxt,
 
     let cc = lib::llvm::CCallConv;
     alt abi {
-      ast::native_abi_rust_intrinsic { ret; }
+      ast::native_abi_rust_intrinsic {
+        for item in native_mod.items { get_item_val(ccx, item.id); }
+        ret;
+      }
       ast::native_abi_cdecl { cc = lib::llvm::CCallConv; }
       ast::native_abi_stdcall { cc = lib::llvm::X86StdcallCallConv; }
     }
@@ -248,17 +252,9 @@ fn trans_native_mod(ccx: crate_ctxt,
         ast::native_item_fn(fn_decl, tps) {
           let id = native_item.id;
           let tys = c_stack_tys(ccx, id);
-          alt ccx.item_ids.find(id) {
-            some(llwrapfn) {
-              let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
-              build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
-            }
-            none {
-              ccx.sess.span_bug(
-                  native_item.span,
-                  "unbound function item in trans_native_mod");
-            }
-          }
+          let llwrapfn = get_item_val(ccx, id);
+          let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
+          build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
         }
       }
     }
@@ -360,3 +356,48 @@ fn register_crust_fn(ccx: crate_ctxt, sp: span,
     register_fn_fuller(ccx, sp, path, "crust fn", node_id,
                        t, lib::llvm::CCallConv, llfty)
 }
+
+fn abi_of_native_fn(ccx: crate_ctxt, i: @ast::native_item)
+    -> ast::native_abi {
+    alt attr::get_meta_item_value_str_by_name(i.attrs, "abi") {
+      none {
+        alt check ccx.tcx.items.get(i.id) {
+          ast_map::node_native_item(_, abi, _) { abi }
+        }
+      }
+      some(_) {
+        alt attr::native_abi(i.attrs) {
+          either::right(abi) { abi }
+          either::left(msg) { ccx.sess.span_fatal(i.span, msg); }
+        }
+      }
+    }
+}
+
+fn decl_native_fn(ccx: crate_ctxt, i: @ast::native_item,
+                  pth: ast_map::path) -> ValueRef {
+    alt i.node {
+      ast::native_item_fn(_, tps) {
+        let node_type = ty::node_id_to_type(ccx.tcx, i.id);
+        alt abi_of_native_fn(ccx, i) {
+          ast::native_abi_rust_intrinsic {
+            // For intrinsics: link the function directly to the intrinsic
+            // function itself.
+            let fn_type = type_of_fn_from_ty(
+                ccx, node_type, param_bounds(ccx, tps));
+            let ri_name = "rust_intrinsic_" + native::link_name(i);
+            ccx.item_symbols.insert(i.id, ri_name);
+            get_extern_fn(ccx.externs, ccx.llmod, ri_name,
+                          lib::llvm::CCallConv, fn_type)
+          }
+
+          ast::native_abi_cdecl | ast::native_abi_stdcall {
+            // For true external functions: create a rust wrapper
+            // and link to that.  The rust wrapper will handle
+            // switching to the C stack.
+            register_fn(ccx, i.span, pth, "native fn", tps, i.id)
+          }
+        }
+      }
+    }
+}
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index b940b55d642..fa4e254d934 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -2157,7 +2157,8 @@ fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] {
 
 fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
     if id.crate == ast::local_crate {
-        option::map(cx.tcache.find(id), {|it| it.ty})
+        let t = cx.tcache.get(id).ty;
+        if get(t).struct == ty_nil { none } else { some(t) }
     } else {
         csearch::get_impl_iface(cx, id)
     }
@@ -2203,7 +2204,7 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
             *path + [item_elt]
           }
 
-          ast_map::node_native_item(nitem, path) {
+          ast_map::node_native_item(nitem, _, path) {
             *path + [ast_map::path_name(nitem.ident)]
           }
 
@@ -2216,7 +2217,7 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
           }
 
           ast_map::node_expr(_) | ast_map::node_arg(_, _) |
-          ast_map::node_local(_) | ast_map::node_res_ctor(_) |
+          ast_map::node_local(_) | ast_map::node_ctor(_) |
           ast_map::node_export(_, _) {
             cx.sess.bug(#fmt["cannot find item_path for node %?", node]);
           }
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 78796d1ecc2..998ffa654d4 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -258,7 +258,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
                   some(ast_map::node_item(item, _)) {
                     ty_of_item(tcx, mode, item)
                   }
-                  some(ast_map::node_native_item(native_item, _)) {
+                  some(ast_map::node_native_item(native_item, _, _)) {
                     ty_of_native_item(tcx, mode, native_item)
                   }
                   _ {
@@ -906,7 +906,11 @@ mod collect {
                   }
                 }
               }
-              _ {}
+              _ {
+                // Store the bounds with a nil type.
+                tcx.tcache.insert(local_def(it.id), {bounds: i_bounds,
+                                                     ty: ty::mk_nil(tcx)});
+              }
             }
           }
           ast::item_res(decl, tps, _, dtor_id, ctor_id) {