about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/ast_map.rs32
-rw-r--r--src/comp/middle/freevars.rs1
-rw-r--r--src/comp/middle/inline.rs96
-rw-r--r--src/comp/middle/trans/alt.rs4
-rw-r--r--src/comp/middle/trans/base.rs101
-rw-r--r--src/comp/middle/trans/build.rs3
-rw-r--r--src/comp/middle/trans/closure.rs4
-rw-r--r--src/comp/middle/trans/common.rs20
-rw-r--r--src/comp/middle/trans/debuginfo.rs2
-rw-r--r--src/comp/middle/trans/impl.rs4
-rw-r--r--src/comp/middle/ty.rs5
-rw-r--r--src/comp/middle/typeck.rs14
12 files changed, 238 insertions, 48 deletions
diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs
index aad8afe0b0c..79410158ad5 100644
--- a/src/comp/middle/ast_map.rs
+++ b/src/comp/middle/ast_map.rs
@@ -37,11 +37,8 @@ type map = std::map::map<node_id, ast_node>;
 type ctx = {map: map, mutable path: path, mutable local_id: uint};
 type vt = visit::vt<ctx>;
 
-fn map_crate(c: crate) -> map {
-    let cx = {map: std::map::new_int_hash(),
-              mutable path: [],
-              mutable local_id: 0u};
-    visit::visit_crate(c, cx, visit::mk_vt(@{
+fn mk_ast_map_visitor() -> vt {
+    ret visit::mk_vt(@{
         visit_item: map_item,
         visit_native_item: map_native_item,
         visit_expr: map_expr,
@@ -49,10 +46,33 @@ fn map_crate(c: crate) -> map {
         visit_local: map_local,
         visit_arm: map_arm
         with *visit::default_visitor()
-    }));
+    });
+}
+
+fn map_crate(c: crate) -> map {
+    let cx = {map: std::map::new_int_hash(),
+              mutable path: [],
+              mutable local_id: 0u};
+    visit::visit_crate(c, cx, mk_ast_map_visitor());
     ret cx.map;
 }
 
+// Used for items loaded from external crate that are being inlined into this
+// crate:
+fn map_decoded_item(map: map, path: path, i: @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
+    // alias analysis, which we will not be running on the inlined items, and
+    // even if we did I think it only needs an ordering between local
+    // variables that are simultaneously in scope).
+    let cx = {map: map,
+              mutable path: path,
+              mutable local_id: 0u};
+    let v = mk_ast_map_visitor();
+    v.visit_item(i, cx, v);
+}
+
 fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
           sp: codemap::span, id: node_id, cx: ctx, v: vt) {
     for a in decl.inputs {
diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs
index 8df1fffa919..65a4ae627ea 100644
--- a/src/comp/middle/freevars.rs
+++ b/src/comp/middle/freevars.rs
@@ -11,6 +11,7 @@ import syntax::codemap::span;
 export annotate_freevars;
 export freevar_map;
 export freevar_info;
+export freevar_entry;
 export get_freevars;
 export has_freevars;
 
diff --git a/src/comp/middle/inline.rs b/src/comp/middle/inline.rs
new file mode 100644
index 00000000000..e212cfbcc43
--- /dev/null
+++ b/src/comp/middle/inline.rs
@@ -0,0 +1,96 @@
+import std::map::hashmap;
+import syntax::ast;
+import syntax::ast_util;
+import syntax::visit;
+import middle::typeck::method_map;
+import middle::trans::common::maps;
+import metadata::csearch;
+
+export inline_map;
+export instantiate_inlines;
+
+type inline_map = hashmap<ast::def_id, @ast::item>;
+
+enum ctxt = {
+    tcx: ty::ctxt,
+    maps: maps,
+    inline_map: inline_map,
+    mutable to_process: [@ast::item]
+};
+
+fn instantiate_inlines(tcx: ty::ctxt,
+                       maps: maps,
+                       crate: @ast::crate) -> inline_map {
+    let vt = visit::mk_vt(@{
+        visit_expr: fn@(e: @ast::expr, cx: ctxt, vt: visit::vt<ctxt>) {
+            visit::visit_expr(e, cx, vt);
+            cx.visit_expr(e);
+        }
+        with *visit::default_visitor::<ctxt>()
+    });
+    let inline_map = ast_util::new_def_id_hash();
+    let cx = ctxt({tcx: tcx, maps: maps,
+                   inline_map: inline_map, mutable to_process: []});
+    visit::visit_crate(*crate, cx, vt);
+    while !vec::is_empty(cx.to_process) {
+        let to_process = [];
+        to_process <-> cx.to_process;
+        #debug["Recursively looking at inlined items"];
+        vec::iter(to_process, {|i| visit::visit_item(i, cx, vt)});
+    }
+    ret inline_map;
+}
+
+impl methods for ctxt {
+    fn visit_expr(e: @ast::expr) {
+
+        // Look for fn items or methods that are referenced which
+        // ought to be inlined.
+
+        alt e.node {
+          ast::expr_path(_) {
+            alt self.tcx.def_map.get(e.id) {
+              ast::def_fn(did, _) {
+                self.maybe_enqueue_fn(did);
+              }
+              _ { /* not a fn item, fallthrough */ }
+            }
+          }
+          ast::expr_field(_, _, _) {
+            alt self.maps.method_map.find(e.id) {
+              some(origin) {
+                self.maybe_enqueue_impl_method(origin);
+              }
+              _ { /* not an impl method, fallthrough */ }
+            }
+          }
+          _ { /* fallthrough */ }
+        }
+    }
+
+    fn maybe_enqueue_fn(did: ast::def_id) {
+        if did.crate == ast::local_crate { ret; }
+        if self.inline_map.contains_key(did) { ret; }
+        alt csearch::maybe_get_item_ast(self.tcx, self.maps, did) {
+          none {
+            /* no AST attached, do not inline */
+            #debug["No AST attached to def %s",
+                   ty::item_path_str(self.tcx, did)];
+          }
+          some(item) { /* Found an AST, add to table: */
+            #debug["Inlining def %s", ty::item_path_str(self.tcx, did)];
+            self.to_process += [item];
+            self.inline_map.insert(did, item);
+          }
+        }
+    }
+
+    fn maybe_enqueue_impl_method(_origin: typeck::method_origin) {
+        // alt method_origin {
+        //   method_static(did) { self.maybe_enqueue_fn(did); }
+        //   method_param(_, _, _, _) | method_iface(_, _) {
+        //     /* fallthrough */
+        //   }
+        // }
+    }
+}
diff --git a/src/comp/middle/trans/alt.rs b/src/comp/middle/trans/alt.rs
index d461781e719..9e5333ade64 100644
--- a/src/comp/middle/trans/alt.rs
+++ b/src/comp/middle/trans/alt.rs
@@ -585,7 +585,7 @@ fn make_phi_bindings(bcx: block, map: [exit_node],
     if success {
         // Copy references that the alias analysis considered unsafe
         ids.values {|node_id|
-            if bcx.ccx().copy_map.contains_key(node_id) {
+            if bcx.ccx().maps.copy_map.contains_key(node_id) {
                 let local = alt bcx.fcx.lllocals.find(node_id) {
                   some(local_mem(x)) { x }
                   _ { bcx.tcx().sess.bug("Someone \
@@ -675,7 +675,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
     alt pat.node {
       ast::pat_ident(_,inner) {
         if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; }
-        if make_copy || ccx.copy_map.contains_key(pat.id) {
+        if make_copy || ccx.maps.copy_map.contains_key(pat.id) {
             let ty = node_id_type(bcx, pat.id);
             let llty = type_of::type_of(ccx, ty);
             let alloc = alloca(bcx, llty);
diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs
index 4ec06b83772..e05f4e12855 100644
--- a/src/comp/middle/trans/base.rs
+++ b/src/comp/middle/trans/base.rs
@@ -21,6 +21,7 @@ import driver::session;
 import session::session;
 import front::attr;
 import middle::freevars::*;
+import middle::inline::inline_map;
 import back::{link, abi, upcall};
 import syntax::{ast, ast_util, codemap};
 import ast_util::local_def;
@@ -59,6 +60,14 @@ enum dest {
     ignore,
 }
 
+fn dest_str(ccx: crate_ctxt, d: dest) -> str {
+    alt d {
+      by_val(v) { #fmt["by_val(%s)", val_str(ccx.tn, *v)] }
+      save_in(v) { #fmt["save_in(%s)", val_str(ccx.tn, v)] }
+      ignore { "ignore" }
+    }
+}
+
 fn empty_dest_cell() -> @mutable ValueRef {
     ret @mutable llvm::LLVMGetUndef(T_nil());
 }
@@ -1561,7 +1570,7 @@ fn trans_lit(cx: block, lit: ast::lit, dest: dest) -> block {
 fn trans_unary(bcx: block, op: ast::unop, e: @ast::expr,
                un_expr: @ast::expr, dest: dest) -> block {
     // Check for user-defined method call
-    alt bcx.ccx().method_map.find(un_expr.id) {
+    alt bcx.ccx().maps.method_map.find(un_expr.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(un_expr);
         let fty = node_id_type(bcx, callee_id);
@@ -1741,7 +1750,7 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
     assert (lhs_res.kind == owned);
 
     // A user-defined operator method
-    alt bcx.ccx().method_map.find(ex.id) {
+    alt bcx.ccx().maps.method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
         let fty = node_id_type(bcx, callee_id);
@@ -1852,7 +1861,7 @@ fn trans_lazy_binop(bcx: block, op: lazy_binop_ty, a: @ast::expr,
 fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
                 rhs: @ast::expr, dest: dest, ex: @ast::expr) -> block {
     // User-defined operators
-    alt bcx.ccx().method_map.find(ex.id) {
+    alt bcx.ccx().maps.method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
         let fty = node_id_type(bcx, callee_id);
@@ -2110,8 +2119,29 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
                   substs: option<([ty::t], typeck::dict_res)>)
     -> lval_maybe_callee {
     let ccx = bcx.ccx();
+    let tcx = ccx.tcx;
     let tys = node_id_type_params(bcx, id);
-    let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
+    let tpt = ty::lookup_item_type(tcx, fn_id);
+
+    // Check whether this fn has an inlined copy and, if so, redirect fn_id to
+    // the local id of the inlined copy.
+    let fn_id = {
+        if fn_id.crate == ast::local_crate {
+            fn_id
+        } else {
+            alt ccx.inline_map.find(fn_id) {
+              none { fn_id }
+              some(item) {
+                #debug["Found inlined version of %s with id %d",
+                       ty::item_path_str(tcx, fn_id),
+                       item.id];
+                {crate: ast::local_crate,
+                 node: item.id}
+              }
+            }
+        }
+    };
+
     // The awkwardness below mostly stems from the fact that we're mixing
     // monomorphized and non-monomorphized functions at the moment. If
     // monomorphizing becomes the only approach, this'll be much simpler.
@@ -2126,7 +2156,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
             } else { none }
           }
           none {
-            alt ccx.dict_map.find(id) {
+            alt ccx.maps.dict_map.find(id) {
               some(dicts) {
                 alt impl::resolve_dicts_in_fn_ctxt(bcx.fcx, dicts) {
                   some(dicts) { monomorphic_fn(ccx, fn_id, tys, some(dicts)) }
@@ -2146,6 +2176,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
           none {}
         }
     }
+
     let val = if fn_id.crate == ast::local_crate {
         // Internal reference.
         assert (ccx.item_ids.contains_key(fn_id.node));
@@ -2181,7 +2212,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
                             static_tis: tis,
                             tydescs: tydescs,
                             param_bounds: tpt.bounds,
-                            origins: ccx.dict_map.find(id)});
+                            origins: ccx.maps.dict_map.find(id)});
     }
     ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
 }
@@ -2347,7 +2378,7 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr,
 
 fn expr_is_lval(bcx: block, e: @ast::expr) -> bool {
     let ccx = bcx.ccx();
-    ty::expr_is_lval(ccx.method_map, e)
+    ty::expr_is_lval(ccx.maps.method_map, e)
 }
 
 fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
@@ -2356,7 +2387,7 @@ fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
       ast::expr_field(base, ident, _) {
         // Lval means this is a record field, so not a method
         if !expr_is_lval(bcx, e) {
-            alt bcx.ccx().method_map.find(e.id) {
+            alt bcx.ccx().maps.method_map.find(e.id) {
               some(origin) { // An impl method
                 ret impl::trans_method_callee(bcx, e.id, base, origin);
               }
@@ -2553,7 +2584,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef,
             val = do_spill_noroot(bcx, val);
             copied = true;
         }
-        if ccx.copy_map.contains_key(e.id) && lv.kind != temporary {
+        if ccx.maps.copy_map.contains_key(e.id) && lv.kind != temporary {
             if !copied {
                 let alloc = alloc_ty(bcx, e_ty);
                 bcx = copy_val(alloc.bcx, INIT, alloc.val,
@@ -2568,7 +2599,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef,
     } else if arg_mode == ast::by_copy || arg_mode == ast::by_move {
         let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
         let move_out = arg_mode == ast::by_move ||
-            ccx.last_uses.contains_key(e.id);
+            ccx.maps.last_uses.contains_key(e.id);
         bcx = cx;
         if lv.kind == temporary { revoke_clean(bcx, val); }
         if lv.kind == owned || !ty::type_is_immediate(e_ty) {
@@ -2983,7 +3014,11 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
     let tcx = bcx.tcx();
     debuginfo::update_source_pos(bcx, e.span);
 
-    #debug["trans_expr(%s,%?)", expr_to_str(e), dest];
+    #debug["trans_expr(e=%s,e.id=%d,dest=%s,ty=%s)",
+           expr_to_str(e),
+           e.id,
+           dest_str(bcx.ccx(), dest),
+           ty_to_str(tcx, expr_ty(bcx, e))];
 
     if expr_is_lval(bcx, e) {
         ret lval_to_dps(bcx, e, dest);
@@ -3056,7 +3091,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
       }
       ast::expr_index(base, idx) {
         // If it is here, it's not an lval, so this is a user-defined index op
-        let origin = bcx.ccx().method_map.get(e.id);
+        let origin = bcx.ccx().maps.method_map.get(e.id);
         let callee_id = ast_util::op_expr_callee_id(e);
         let fty = node_id_type(bcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
@@ -3128,7 +3163,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
         assert kind == owned;
         ret store_temp_expr(bcx, DROP_EXISTING, addr, src_r,
                             expr_ty(bcx, src),
-                            bcx.ccx().last_uses.contains_key(src.id));
+                            bcx.ccx().maps.last_uses.contains_key(src.id));
       }
       ast::expr_move(dst, src) {
         // FIXME: calculate copy init-ness in typestate.
@@ -3164,7 +3199,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
 fn lval_to_dps(bcx: block, e: @ast::expr, dest: dest) -> block {
     let lv = trans_lval(bcx, e), ccx = bcx.ccx();
     let {bcx, val, kind} = lv;
-    let last_use = kind == owned && ccx.last_uses.contains_key(e.id);
+    let last_use = kind == owned && ccx.maps.last_uses.contains_key(e.id);
     let ty = expr_ty(bcx, e);
     alt dest {
       by_val(cell) {
@@ -3717,8 +3752,8 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
     // Do not allocate space for locals that can be kept immediate.
     let ccx = cx.ccx();
     if option::is_some(simple_name) &&
-       !ccx.mutbl_map.contains_key(local.node.pat.id) &&
-       !ccx.last_uses.contains_key(local.node.pat.id) &&
+       !ccx.maps.mutbl_map.contains_key(local.node.pat.id) &&
+       !ccx.maps.last_uses.contains_key(local.node.pat.id) &&
        ty::type_is_immediate(t) {
         alt local.node.init {
           some({op: ast::init_assign, _}) { ret cx; }
@@ -4258,6 +4293,12 @@ fn trans_mod(ccx: crate_ctxt, m: ast::_mod) {
     for item in m.items { trans_item(ccx, *item); }
 }
 
+fn trans_inlined_items(ccx: crate_ctxt, inline_map: inline_map) {
+    inline_map.values {|item|
+        trans_item(ccx, *item)
+    }
+}
+
 fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
     // Bit of a kludge: pick the fn typeref out of the pair.
     ret struct_elt(llpairty, 0u);
@@ -4290,6 +4331,9 @@ fn register_fn_fuller(ccx: crate_ctxt, sp: span, path: path, _flav: str,
     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",
+           val_str(ccx.tn, llfn), node_id, ast_map::path_to_str(path)];
+
     let is_main = is_main_name(path) && !ccx.sess.building_library;
     if is_main { create_main_wrapper(ccx, sp, llfn, node_type); }
 }
@@ -4519,6 +4563,13 @@ fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
     }));
 }
 
+fn collect_inlined_items(ccx: crate_ctxt, inline_map: inline::inline_map) {
+    let abi = @mutable none::<ast::native_abi>;
+    inline_map.values {|item|
+        collect_item(ccx, abi, item);
+    }
+}
+
 // The constant translation pass.
 fn trans_constant(ccx: crate_ctxt, it: @ast::item) {
     alt it.node {
@@ -4718,10 +4769,8 @@ fn write_abi_version(ccx: crate_ctxt) {
 }
 
 fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
-               output: str, emap: resolve::exp_map, amap: ast_map::map,
-               mutbl_map: mutbl::mutbl_map, copy_map: alias::copy_map,
-               last_uses: last_use::last_uses, impl_map: resolve::impl_map,
-               method_map: typeck::method_map, dict_map: typeck::dict_map)
+               output: str, emap: resolve::exp_map, maps: maps,
+               inline_map: inline::inline_map)
     -> (ModuleRef, link::link_meta) {
     let sha = std::sha1::mk_sha1();
     let link_meta = link::build_link_meta(sess, *crate, output, sha);
@@ -4769,6 +4818,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
     } else {
         option::none
     };
+
     let ccx =
         @{sess: sess,
           llmod: llmod,
@@ -4777,7 +4827,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           externs: new_str_hash::<ValueRef>(),
           intrinsics: intrinsics,
           item_ids: new_int_hash::<ValueRef>(),
-          ast_map: amap,
           exp_map: emap,
           item_symbols: new_int_hash::<str>(),
           mutable main_fn: none::<ValueRef>,
@@ -4796,12 +4845,8 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           type_sha1s: ty::new_ty_hash(),
           type_short_names: ty::new_ty_hash(),
           tcx: tcx,
-          mutbl_map: mutbl_map,
-          copy_map: copy_map,
-          last_uses: last_uses,
-          impl_map: impl_map,
-          method_map: method_map,
-          dict_map: dict_map,
+          maps: maps,
+          inline_map: inline_map,
           stats:
               {mutable n_static_tydescs: 0u,
                mutable n_derived_tydescs: 0u,
@@ -4823,8 +4868,10 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           dbg_cx: dbg_cx,
           mutable do_not_commit_warning_issued: false};
     collect_items(ccx, crate);
+    collect_inlined_items(ccx, inline_map);
     trans_constants(ccx, crate);
     trans_mod(ccx, crate.node.module);
+    trans_inlined_items(ccx, inline_map);
     fill_crate_map(ccx, crate_map);
     emit_tydescs(ccx);
     gen_shape_tables(ccx);
diff --git a/src/comp/middle/trans/build.rs b/src/comp/middle/trans/build.rs
index 0559a6b02af..767b2c0b621 100644
--- a/src/comp/middle/trans/build.rs
+++ b/src/comp/middle/trans/build.rs
@@ -322,6 +322,9 @@ fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
 
 fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
     if cx.unreachable { ret; }
+    #debug["Store %s -> %s",
+           val_str(cx.ccx().tn, Val),
+           val_str(cx.ccx().tn, Ptr)];
     llvm::LLVMBuildStore(B(cx), Val, Ptr);
 }
 
diff --git a/src/comp/middle/trans/closure.rs b/src/comp/middle/trans/closure.rs
index 3f7274deae4..d8a66750e90 100644
--- a/src/comp/middle/trans/closure.rs
+++ b/src/comp/middle/trans/closure.rs
@@ -277,6 +277,7 @@ fn store_environment(
     let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
     let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mutbl:ast::m_imm});
     let llbox = cast_if_we_can(bcx, llbox, cboxptr_ty);
+    #debug["tuplify_box_ty = %s", ty_to_str(tcx, cbox_ty)];
 
     // If necessary, copy tydescs describing type parameters into the
     // appropriate slot in the closure.
@@ -298,8 +299,9 @@ fn store_environment(
     }
 
     // Copy expr values into boxed bindings.
-    // Silly check
     vec::iteri(bound_values) { |i, bv|
+        #debug["Copy %s into closure", ev_to_str(ccx, bv)];
+
         if (!ccx.sess.opts.no_asm_comments) {
             add_comment(bcx, #fmt("Copy %s into closure",
                                   ev_to_str(ccx, bv)));
diff --git a/src/comp/middle/trans/common.rs b/src/comp/middle/trans/common.rs
index 1c04bc8c4c6..c546ce5341d 100644
--- a/src/comp/middle/trans/common.rs
+++ b/src/comp/middle/trans/common.rs
@@ -19,6 +19,7 @@ import lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
 import lib::llvm::{True, False, Bool};
 import metadata::csearch;
 import ast_map::path;
+import middle::inline::inline_map;
 
 type namegen = fn@(str) -> str;
 fn new_namegen() -> namegen {
@@ -63,6 +64,16 @@ type stats =
 
 resource BuilderRef_res(B: BuilderRef) { llvm::LLVMDisposeBuilder(B); }
 
+// Misc. auxiliary maps used in the crate_ctxt
+type maps = {
+    mutbl_map: middle::mutbl::mutbl_map,
+    copy_map: middle::alias::copy_map,
+    last_uses: middle::last_use::last_uses,
+    impl_map: middle::resolve::impl_map,
+    method_map: middle::typeck::method_map,
+    dict_map: middle::typeck::dict_map
+};
+
 // Crate context.  Every crate we compile has one of these.
 type crate_ctxt = @{
      sess: session::session,
@@ -72,7 +83,6 @@ type crate_ctxt = @{
      externs: hashmap<str, ValueRef>,
      intrinsics: hashmap<str, ValueRef>,
      item_ids: hashmap<ast::node_id, ValueRef>,
-     ast_map: ast_map::map,
      exp_map: resolve::exp_map,
      item_symbols: hashmap<ast::node_id, str>,
      mutable main_fn: option<ValueRef>,
@@ -91,12 +101,8 @@ type crate_ctxt = @{
      type_sha1s: hashmap<ty::t, str>,
      type_short_names: hashmap<ty::t, str>,
      tcx: ty::ctxt,
-     mutbl_map: mutbl::mutbl_map,
-     copy_map: alias::copy_map,
-     last_uses: last_use::last_uses,
-     impl_map: resolve::impl_map,
-     method_map: typeck::method_map,
-     dict_map: typeck::dict_map,
+     maps: maps,
+     inline_map: inline_map,
      stats: stats,
      upcalls: @upcall::upcalls,
      tydesc_type: TypeRef,
diff --git a/src/comp/middle/trans/debuginfo.rs b/src/comp/middle/trans/debuginfo.rs
index 47024432b4e..47a3d2e5716 100644
--- a/src/comp/middle/trans/debuginfo.rs
+++ b/src/comp/middle/trans/debuginfo.rs
@@ -780,7 +780,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
     let sp = option::get(fcx.span);
     log(debug, codemap::span_to_str(sp, cx.sess.codemap));
 
-    let (ident, ret_ty, id) = alt cx.ast_map.get(fcx.id) {
+    let (ident, ret_ty, id) = alt cx.tcx.items.get(fcx.id) {
       ast_map::node_item(item, _) {
         alt item.node {
           ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) {
diff --git a/src/comp/middle/trans/impl.rs b/src/comp/middle/trans/impl.rs
index 45c9499f197..00345e8ae02 100644
--- a/src/comp/middle/trans/impl.rs
+++ b/src/comp/middle/trans/impl.rs
@@ -134,7 +134,7 @@ fn trans_vtable_callee(bcx: block, env: callee_env, dict: ValueRef,
                                 static_tis: tis,
                                 tydescs: tydescs,
                                 param_bounds: method.tps,
-                                origins: ccx.dict_map.find(callee_id)});
+                                origins: ccx.maps.dict_map.find(callee_id)});
     }
     {bcx: bcx, val: mptr, kind: owned,
      env: env,
@@ -531,7 +531,7 @@ fn trans_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: dest)
     let result = get_dest_addr(dest);
     Store(bcx, box, PointerCast(bcx, GEPi(bcx, result, [0, 1]),
                                 T_ptr(val_ty(box))));
-    let {bcx, val: dict} = get_dict(bcx, ccx.dict_map.get(id)[0]);
+    let {bcx, val: dict} = get_dict(bcx, ccx.maps.dict_map.get(id)[0]);
     Store(bcx, dict, PointerCast(bcx, GEPi(bcx, result, [0, 0]),
                                  T_ptr(val_ty(dict))));
     bcx
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index a0189264446..a7e218e581b 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -129,6 +129,7 @@ export param_bound, param_bounds, bound_copy, bound_send, bound_iface;
 export param_bounds_to_kind;
 export default_arg_mode_for_ty;
 export item_path;
+export item_path_str;
 
 // Data types
 
@@ -2174,6 +2175,10 @@ fn substd_enum_variants(cx: ctxt, id: ast::def_id, tps: [ty::t])
     }
 }
 
+fn item_path_str(cx: ctxt, id: ast::def_id) -> str {
+    ast_map::path_to_str(item_path(cx, id))
+}
+
 fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
     if id.crate != ast::local_crate {
         csearch::get_item_path(cx, id)
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 88753b06091..0343c2c102f 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -444,8 +444,18 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
         // call to resolve any named types.
         let tpt = {
             let t0 = ast_ty_to_ty(tcx, mode, t);
-            {bounds: ty_param_bounds(tcx, mode, tps),
-             ty: ty::mk_with_id(tcx, t0, def_id)}
+            let t1 = {
+                // Do not associate a def id with a named, parameterized type
+                // like "foo<X>".  This is because otherwise ty_to_str will
+                // print the name as merely "foo", as it has no way to
+                // reconstruct the value of X.
+                if vec::is_empty(tps) {
+                    ty::mk_with_id(tcx, t0, def_id)
+                } else {
+                    t0
+                }
+            };
+            {bounds: ty_param_bounds(tcx, mode, tps), ty: t1}
         };
         tcx.tcache.insert(local_def(it.id), tpt);
         ret tpt;