about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/comp/back/link.rs27
-rw-r--r--src/comp/metadata/encoder.rs4
-rw-r--r--src/comp/middle/ast_map.rs69
-rw-r--r--src/comp/middle/debuginfo.rs6
-rw-r--r--src/comp/middle/resolve.rs3
-rw-r--r--src/comp/middle/shape.rs9
-rw-r--r--src/comp/middle/trans/alt.rs8
-rw-r--r--src/comp/middle/trans/base.rs465
-rw-r--r--src/comp/middle/trans/build.rs8
-rw-r--r--src/comp/middle/trans/closure.rs45
-rw-r--r--src/comp/middle/trans/common.rs38
-rw-r--r--src/comp/middle/trans/impl.rs45
-rw-r--r--src/comp/middle/ty.rs2
-rw-r--r--src/comp/middle/typeck.rs8
-rw-r--r--src/comp/util/common.rs6
-rw-r--r--src/rustdoc/attr_pass.rs8
-rw-r--r--src/rustdoc/prune_unexported_pass.rs2
-rw-r--r--src/rustdoc/tystr_pass.rs30
18 files changed, 383 insertions, 400 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index 0052cdd352a..eee0c60599f 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -18,6 +18,7 @@ import syntax::ast;
 import syntax::print::pprust;
 import lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False};
 import util::filesearch;
+import middle::ast_map::{path, path_mod, path_name};
 
 enum output_type {
     output_type_none,
@@ -514,25 +515,27 @@ fn get_symbol_hash(ccx: @crate_ctxt, t: ty::t) -> str {
     ret hash;
 }
 
-fn mangle(ss: [str]) -> str {
+fn mangle(ss: path) -> str {
     // Follow C++ namespace-mangling style
 
     let n = "_ZN"; // Begin name-sequence.
 
-    for s: str in ss { n += #fmt["%u%s", str::byte_len(s), s]; }
+    for s in ss {
+        alt s { path_name(s) | path_mod(s) {
+          n += #fmt["%u%s", str::byte_len(s), s];
+        } }
+    }
     n += "E"; // End name-sequence.
-
-    ret n;
+    n
 }
 
-fn exported_name(path: [str], hash: str, _vers: str) -> str {
+fn exported_name(path: path, hash: str, _vers: str) -> str {
     // FIXME: versioning isn't working yet
-
-    ret mangle(path + [hash]); //  + "@" + vers;
+    ret mangle(path + [path_name(hash)]); //  + "@" + vers;
 
 }
 
-fn mangle_exported_name(ccx: @crate_ctxt, path: [str], t: ty::t) -> str {
+fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> str {
     let hash = get_symbol_hash(ccx, t);
     ret exported_name(path, hash, ccx.link_meta.vers);
 }
@@ -541,15 +544,15 @@ fn mangle_internal_name_by_type_only(ccx: @crate_ctxt, t: ty::t, name: str) ->
    str {
     let s = util::ppaux::ty_to_short_str(ccx.tcx, t);
     let hash = get_symbol_hash(ccx, t);
-    ret mangle([name, s, hash]);
+    ret mangle([path_name(name), path_name(s), path_name(hash)]);
 }
 
-fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: [str],
+fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: path,
                                         flav: str) -> str {
-    ret mangle(path + [ccx.names(flav)]);
+    ret mangle(path + [path_name(ccx.names(flav))]);
 }
 
-fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: [str]) -> str {
+fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: path) -> str {
     ret mangle(path);
 }
 
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index c5823896d9c..8648d487827 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -447,11 +447,11 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
     encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, "");
     ecx.ccx.ast_map.items {|key, val|
         alt val {
-          middle::ast_map::node_item(i) {
+          middle::ast_map::node_item(i, _) {
             index += [{val: key, pos: ebml_w.writer.tell()}];
             encode_info_for_item(ecx, ebml_w, i, index);
           }
-          middle::ast_map::node_native_item(i) {
+          middle::ast_map::node_native_item(i, _) {
             index += [{val: key, pos: ebml_w.writer.tell()}];
             encode_info_for_native_item(ecx, ebml_w, i);
           }
diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs
index 97881ca17a2..c47c0d9b9f4 100644
--- a/src/comp/middle/ast_map.rs
+++ b/src/comp/middle/ast_map.rs
@@ -4,10 +4,13 @@ import syntax::ast::*;
 import syntax::ast_util;
 import syntax::{visit, codemap};
 
+enum path_elt { path_mod(str), path_name(str) }
+type path = [path_elt];
+
 enum ast_node {
-    node_item(@item),
-    node_native_item(@native_item),
-    node_method(@method),
+    node_item(@item, @path),
+    node_native_item(@native_item, @path),
+    node_method(@method, @path),
     node_expr(@expr),
     // Locals are numbered, because the alias analysis needs to know in which
     // order they are introduced.
@@ -17,66 +20,78 @@ enum ast_node {
 }
 
 type map = std::map::map<node_id, ast_node>;
-type ctx = @{map: map, mutable local_id: uint};
+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 local_id: 0u};
-
-    let v_map = visit::mk_simple_visitor
-        (@{visit_item: bind map_item(cx, _),
-           visit_native_item: bind map_native_item(cx, _),
-           visit_expr: bind map_expr(cx, _),
-           visit_fn: bind map_fn(cx, _, _, _, _, _),
-           visit_local: bind map_local(cx, _),
-           visit_arm: bind map_arm(cx, _)
-           with *visit::default_simple_visitor()});
-    visit::visit_crate(c, (), v_map);
+    let cx = {map: std::map::new_int_hash(),
+              mutable path: [],
+              mutable local_id: 0u};
+    visit::visit_crate(c, cx, 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,
+        visit_arm: map_arm
+        with *visit::default_visitor()
+    }));
     ret cx.map;
 }
 
-fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
-          _sp: codemap::span, _id: node_id) {
+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 {
         cx.map.insert(a.id, node_arg(a, cx.local_id));
         cx.local_id += 1u;
     }
+    visit::visit_fn(fk, decl, body, sp, id, cx, v);
 }
 
-fn map_local(cx: ctx, loc: @local) {
+fn map_local(loc: @local, cx: ctx, v: vt) {
     pat_util::pat_bindings(loc.node.pat) {|p_id, _s, _p|
         cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
+    visit::visit_local(loc, cx, v);
 }
 
-fn map_arm(cx: ctx, arm: arm) {
+fn map_arm(arm: arm, cx: ctx, v: vt) {
     pat_util::pat_bindings(arm.pats[0]) {|p_id, _s, _p|
         cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
+    visit::visit_arm(arm, cx, v);
 }
 
-fn map_item(cx: ctx, i: @item) {
-    cx.map.insert(i.id, node_item(i));
+fn map_item(i: @item, cx: ctx, v: vt) {
+    cx.map.insert(i.id, node_item(i, @cx.path));
     alt i.node {
       item_impl(_, _, _, ms) {
-        for m in ms { cx.map.insert(m.id, node_method(m)); }
+        for m in ms { cx.map.insert(m.id, node_method(m, @cx.path)); }
       }
       item_res(_, _, _, dtor_id, ctor_id) {
         cx.map.insert(ctor_id, node_res_ctor(i));
-        cx.map.insert(dtor_id, node_item(i));
+        cx.map.insert(dtor_id, node_item(i, @cx.path));
       }
       _ { }
     }
+    alt i.node {
+      item_mod(_) | item_native_mod(_) { cx.path += [path_mod(i.ident)]; }
+      _ { cx.path += [path_name(i.ident)]; }
+    }
+    visit::visit_item(i, cx, v);
+    vec::pop(cx.path);
 }
 
-fn map_native_item(cx: ctx, i: @native_item) {
-    cx.map.insert(i.id, node_native_item(i));
+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(cx: ctx, ex: @expr) {
+fn map_expr(ex: @expr, cx: ctx, v: vt) {
     cx.map.insert(ex.id, node_expr(ex));
+    visit::visit_expr(ex, cx, v);
 }
 
 // Local Variables:
diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs
index 8732fa784a5..187e0a88a7a 100644
--- a/src/comp/middle/debuginfo.rs
+++ b/src/comp/middle/debuginfo.rs
@@ -761,7 +761,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
     log(debug, codemap::span_to_str(sp, cx.sess.codemap));
 
     let (ident, ret_ty, id) = alt cx.ast_map.get(fcx.id) {
-      ast_map::node_item(item) {
+      ast_map::node_item(item, _) {
         alt item.node {
           ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) {
             (item.ident, decl.output, item.id)
@@ -770,7 +770,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
                 bound to non-function"); }
         }
       }
-      ast_map::node_method(method) {
+      ast_map::node_method(method, _) {
           (method.ident, method.decl.output, method.id)
       }
       ast_map::node_res_ctor(item) {
@@ -808,7 +808,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
       option::none {}
     }
 
-    let path = str::connect(fcx.lcx.path + [ident], "::");
+    let path = path_str(fcx.path);
 
     let loc = codemap::lookup_char_pos(cx.sess.codemap,
                                        sp.lo);
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index d708ddf4b42..4e4caa2848c 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -480,7 +480,8 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
     // is this a main fn declaration?
     alt fk {
       visit::fk_item_fn(nm, _) {
-        if is_main_name([nm]) && !e.sess.building_library {
+        if is_main_name([ast_map::path_name(nm)]) &&
+           !e.sess.building_library {
             // This is a main function -- set it in the session
             // as the main ID
             e.sess.main_fn = some((id, sp));
diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs
index c5746974fe2..ef458a54f97 100644
--- a/src/comp/middle/shape.rs
+++ b/src/comp/middle/shape.rs
@@ -470,15 +470,6 @@ fn shape_of_variant(ccx: @crate_ctxt, v: ty::variant_info,
     ret s;
 }
 
-//fn variant_names(ccx: @crate_ctxt, tag_id: ast::def_id) -> [str] {
-//    assert ast::local_crate == tag_id.crate;
-//    alt ccx.tcx.items.get(tag_id.node) {
-//      ast_map::node_item(@{node: ast::item_tag(variants, _), _}) {
-//        vec::map(variants) {|variant| variant.node.name}
-//      }
-//    }
-//}
-
 fn gen_enum_shapes(ccx: @crate_ctxt) -> ValueRef {
     // Loop over all the enum variants and write their shapes into a
     // data buffer. As we do this, it's possible for us to discover
diff --git a/src/comp/middle/trans/alt.rs b/src/comp/middle/trans/alt.rs
index b63a90e7f96..c2dddba4d5a 100644
--- a/src/comp/middle/trans/alt.rs
+++ b/src/comp/middle/trans/alt.rs
@@ -265,7 +265,7 @@ fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
 fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
                         vdefs: {enm: def_id, var: def_id}, val: ValueRef) ->
    {vals: [ValueRef], bcx: @block_ctxt} {
-    let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
+    let ccx = bcx.fcx.ccx, bcx = bcx;
     // invariant:
     // pat_id must have the same length ty_param_substs as vdefs?
     let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
@@ -412,7 +412,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     let vals_left =
         vec::slice(vals, 0u, col) +
             vec::slice(vals, col + 1u, vec::len(vals));
-    let ccx = bcx.fcx.lcx.ccx;
+    let ccx = bcx.fcx.ccx;
     let pat_id = 0;
     for br: match_branch in m {
         // Find a real id (we're adding placeholder wildcard patterns, but
@@ -692,7 +692,7 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms_: [ast::arm],
     }
 
     let exit_map = [];
-    let t = base::node_id_type(cx.fcx.lcx.ccx, expr.id);
+    let t = base::node_id_type(cx.fcx.ccx, expr.id);
     let vr = base::spill_if_immediate(er.bcx, er.val, t);
     compile_submatch(vr.bcx, match, [vr.val],
                      bind mk_fail(alt_cx, expr.span, fail_cx), exit_map);
@@ -719,7 +719,7 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms_: [ast::arm],
 // Not alt-related, but similar to the pattern-munging code above
 fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
                         make_copy: bool) -> @block_ctxt {
-    let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
+    let ccx = bcx.fcx.ccx, bcx = bcx;
 
     // Necessary since bind_irrefutable_pat is called outside trans_alt
     alt normalize_pat(bcx_tcx(bcx), pat).node {
diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs
index 76493e767dc..3332e06c841 100644
--- a/src/comp/middle/trans/base.rs
+++ b/src/comp/middle/trans/base.rs
@@ -24,6 +24,7 @@ import front::attr;
 import middle::freevars::*;
 import back::{link, abi, upcall};
 import syntax::{ast, ast_util, codemap};
+import ast_util::local_def;
 import syntax::visit;
 import syntax::codemap::span;
 import syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str};
@@ -44,6 +45,7 @@ import util::ppaux::{ty_to_str, ty_to_short_str};
 import shape::static_size_of_enum;
 import common::*;
 import build::*;
+import ast_map::{path, path_mod, path_name};
 
 fn type_of_1(bcx: @block_ctxt, t: ty::t) -> TypeRef {
     let cx = bcx_ccx(bcx);
@@ -222,13 +224,12 @@ fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
     }
 }
 
-fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt,
-                                 tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
-    let cx = lcx.ccx;
+fn type_of_ty_param_bounds_and_ty
+    (ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
     let t = tpt.ty;
-    alt ty::struct(cx.tcx, t) {
+    alt ty::struct(ccx.tcx, t) {
       ty::ty_fn(_) {
-        ret type_of_fn_from_ty(cx, t, *tpt.bounds);
+        ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
       }
       _ {
         // fall through
@@ -237,8 +238,8 @@ fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt,
     // FIXME: could have a precondition on tpt, but that
     // doesn't work right now because one predicate can't imply
     // another
-    check (type_has_static_size(cx, t));
-    type_of(cx, t)
+    check type_has_static_size(ccx, t);
+    type_of(ccx, t)
 }
 
 fn type_of_or_i8(bcx: @block_ctxt, typ: ty::t) -> TypeRef {
@@ -329,7 +330,7 @@ fn get_simple_extern_fn(cx: @block_ctxt,
                         externs: hashmap<str, ValueRef>,
                         llmod: ModuleRef,
                         name: str, n_args: int) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     let inputs = vec::init_elt::<TypeRef>(n_args as uint, ccx.int_type);
     let output = ccx.int_type;
     let t = T_fn(inputs, output);
@@ -975,7 +976,7 @@ fn get_static_tydesc(cx: @block_ctxt, t: ty::t, ty_params: [uint])
       some(info) { ret info; }
       none {
         bcx_ccx(cx).stats.n_static_tydescs += 1u;
-        let info = declare_tydesc(cx.fcx.lcx, t, ty_params);
+        let info = declare_tydesc(cx.fcx.ccx, t, ty_params);
         bcx_ccx(cx).tydescs.insert(t, info);
         ret info;
       }
@@ -1004,18 +1005,17 @@ fn set_custom_stack_growth_fn(f: ValueRef) {
     llvm::LLVMAddFunctionAttr(f, 0u as c_uint, 1u as c_uint);
 }
 
-fn set_glue_inlining(cx: @local_ctxt, f: ValueRef, t: ty::t) {
-    if ty::type_is_structural(cx.ccx.tcx, t) {
+fn set_glue_inlining(ccx: @crate_ctxt, f: ValueRef, t: ty::t) {
+    if ty::type_is_structural(ccx.tcx, t) {
         set_no_inline(f);
     } else { set_always_inline(f); }
 }
 
 
 // Generates the declaration for (but doesn't emit) a type descriptor.
-fn declare_tydesc(cx: @local_ctxt, t: ty::t, ty_params: [uint])
+fn declare_tydesc(ccx: @crate_ctxt, t: ty::t, ty_params: [uint])
     -> @tydesc_info {
-    log(debug, "+++ declare_tydesc " + ty_to_str(cx.ccx.tcx, t));
-    let ccx = cx.ccx;
+    log(debug, "+++ declare_tydesc " + ty_to_str(ccx.tcx, t));
     let llsize;
     let llalign;
     if check type_has_static_size(ccx, t) {
@@ -1030,63 +1030,59 @@ fn declare_tydesc(cx: @local_ctxt, t: ty::t, ty_params: [uint])
         llalign = C_int(ccx, 0);
     }
     let name;
-    if cx.ccx.sess.opts.debuginfo {
-        name = mangle_internal_name_by_type_only(cx.ccx, t, "tydesc");
+    if ccx.sess.opts.debuginfo {
+        name = mangle_internal_name_by_type_only(ccx, t, "tydesc");
         name = sanitize(name);
-    } else { name = mangle_internal_name_by_seq(cx.ccx, "tydesc"); }
-    let gvar =
-        str::as_buf(name,
-                    {|buf|
-                        llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
-                    });
+    } else { name = mangle_internal_name_by_seq(ccx, "tydesc"); }
+    let gvar = str::as_buf(name, {|buf|
+        llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
+    });
     let info =
         @{ty: t,
           tydesc: gvar,
           size: llsize,
           align: llalign,
-          mutable take_glue: none::<ValueRef>,
-          mutable drop_glue: none::<ValueRef>,
-          mutable free_glue: none::<ValueRef>,
-          mutable cmp_glue: none::<ValueRef>,
+          mutable take_glue: none,
+          mutable drop_glue: none,
+          mutable free_glue: none,
+          mutable cmp_glue: none,
           ty_params: ty_params};
-    log(debug, "--- declare_tydesc " + ty_to_str(cx.ccx.tcx, t));
+    log(debug, "--- declare_tydesc " + ty_to_str(ccx.tcx, t));
     ret info;
 }
 
 type glue_helper = fn@(@block_ctxt, ValueRef, ty::t);
 
-fn declare_generic_glue(cx: @local_ctxt, t: ty::t, llfnty: TypeRef, name: str)
-   -> ValueRef {
+fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef,
+                        name: str) -> ValueRef {
     let name = name;
     let fn_nm;
-    if cx.ccx.sess.opts.debuginfo {
-        fn_nm = mangle_internal_name_by_type_only(cx.ccx, t, "glue_" + name);
+    if ccx.sess.opts.debuginfo {
+        fn_nm = mangle_internal_name_by_type_only(ccx, t, "glue_" + name);
         fn_nm = sanitize(fn_nm);
-    } else { fn_nm = mangle_internal_name_by_seq(cx.ccx, "glue_" + name); }
-    let llfn = decl_cdecl_fn(cx.ccx.llmod, fn_nm, llfnty);
-    set_glue_inlining(cx, llfn, t);
+    } else { fn_nm = mangle_internal_name_by_seq(ccx, "glue_" + name); }
+    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
+    set_glue_inlining(ccx, llfn, t);
     ret llfn;
 }
 
 // FIXME: was this causing the leak?
-fn make_generic_glue_inner(cx: @local_ctxt, t: ty::t,
+fn make_generic_glue_inner(ccx: @crate_ctxt, t: ty::t,
                            llfn: ValueRef, helper: glue_helper,
                            ty_params: [uint]) -> ValueRef {
-    let fcx = new_fn_ctxt(cx, llfn, none);
+    let fcx = new_fn_ctxt(ccx, [], llfn, none);
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
-    cx.ccx.stats.n_glues_created += 1u;
+    ccx.stats.n_glues_created += 1u;
     // Any nontrivial glue is with values passed *by alias*; this is a
     // requirement since in many contexts glue is invoked indirectly and
     // the caller has no idea if it's dealing with something that can be
     // passed by value.
 
-    let ccx = cx.ccx;
-    let llty =
-        if check type_has_static_size(ccx, t) {
-            T_ptr(type_of(ccx, t))
-        } else { T_ptr(T_i8()) };
+    let llty = if check type_has_static_size(ccx, t) {
+        T_ptr(type_of(ccx, t))
+    } else { T_ptr(T_i8()) };
 
-    let ty_param_count = vec::len::<uint>(ty_params);
+    let ty_param_count = vec::len(ty_params);
     let lltyparams = llvm::LLVMGetParam(llfn, 2u as c_uint);
     let load_env_bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
     let lltydescs = [mutable];
@@ -1109,17 +1105,17 @@ fn make_generic_glue_inner(cx: @local_ctxt, t: ty::t,
     ret llfn;
 }
 
-fn make_generic_glue(cx: @local_ctxt, t: ty::t, llfn: ValueRef,
-                     helper: glue_helper, ty_params: [uint], name: str) ->
-   ValueRef {
-    if !cx.ccx.sess.opts.stats {
-        ret make_generic_glue_inner(cx, t, llfn, helper, ty_params);
+fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
+                     helper: glue_helper, ty_params: [uint], name: str)
+    -> ValueRef {
+    if !ccx.sess.opts.stats {
+        ret make_generic_glue_inner(ccx, t, llfn, helper, ty_params);
     }
 
     let start = time::get_time();
-    let llval = make_generic_glue_inner(cx, t, llfn, helper, ty_params);
+    let llval = make_generic_glue_inner(ccx, t, llfn, helper, ty_params);
     let end = time::get_time();
-    log_fn_time(cx.ccx, "glue " + name + " " + ty_to_short_str(cx.ccx.tcx, t),
+    log_fn_time(ccx, "glue " + name + " " + ty_to_short_str(ccx.tcx, t),
                 start, end);
     ret llval;
 }
@@ -1646,6 +1642,7 @@ fn lazily_emit_all_generic_info_tydesc_glues(cx: @block_ctxt,
 
 fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
                            static_ti: option<@tydesc_info>) {
+    let ccx = cx.fcx.ccx;
     alt static_ti {
       none { }
       some(ti) {
@@ -1655,12 +1652,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue TAKE %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
-                let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "take");
-                ti.take_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                let glue_fn = declare_generic_glue
+                    (ccx, ti.ty, T_glue_fn(ccx), "take");
+                ti.take_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_take_glue,
                                   ti.ty_params, "take");
                 #debug("--- lazily_emit_tydesc_glue TAKE %s",
@@ -1673,12 +1668,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue DROP %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
                 let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "drop");
-                ti.drop_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                    declare_generic_glue(ccx, ti.ty, T_glue_fn(ccx), "drop");
+                ti.drop_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_drop_glue,
                                   ti.ty_params, "drop");
                 #debug("--- lazily_emit_tydesc_glue DROP %s",
@@ -1691,12 +1684,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue FREE %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
                 let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "free");
-                ti.free_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                    declare_generic_glue(ccx, ti.ty, T_glue_fn(ccx), "free");
+                ti.free_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_free_glue,
                                   ti.ty_params, "free");
                 #debug("--- lazily_emit_tydesc_glue FREE %s",
@@ -2541,10 +2532,10 @@ fn lval_no_env(bcx: @block_ctxt, val: ValueRef, kind: lval_kind)
 
 fn trans_external_path(cx: @block_ctxt, did: ast::def_id,
                        tpt: ty::ty_param_bounds_and_ty) -> ValueRef {
-    let lcx = cx.fcx.lcx;
-    let name = csearch::get_symbol(lcx.ccx.sess.cstore, did);
-    ret get_extern_const(lcx.ccx.externs, lcx.ccx.llmod, name,
-                         type_of_ty_param_bounds_and_ty(lcx, tpt));
+    let ccx = cx.fcx.ccx;
+    let name = csearch::get_symbol(ccx.sess.cstore, did);
+    ret get_extern_const(ccx.externs, ccx.llmod, name,
+                         type_of_ty_param_bounds_and_ty(ccx, tpt));
 }
 
 fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
@@ -2580,19 +2571,18 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
     ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
 }
 
-fn lookup_discriminant(lcx: @local_ctxt, vid: ast::def_id) -> ValueRef {
-    let ccx = lcx.ccx;
+fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
     alt ccx.discrims.find(vid) {
       none {
         // It's an external discriminant that we haven't seen yet.
         assert (vid.crate != ast::local_crate);
-        let sym = csearch::get_symbol(lcx.ccx.sess.cstore, vid);
+        let sym = csearch::get_symbol(ccx.sess.cstore, vid);
         let gvar = str::as_buf(sym, {|buf|
             llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
         });
         lib::llvm::SetLinkage(gvar, lib::llvm::ExternalLinkage);
         llvm::LLVMSetGlobalConstant(gvar, True);
-        lcx.ccx.discrims.insert(vid, gvar);
+        ccx.discrims.insert(vid, gvar);
         ret gvar;
       }
       some(llval) { ret llval; }
@@ -2657,7 +2647,7 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
             let bcx = alloc_result.bcx;
             let llenumptr = PointerCast(bcx, llenumblob, T_ptr(llenumty));
             let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
-            let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid);
+            let lldiscrim_gv = lookup_discriminant(bcx.fcx.ccx, vid);
             let lldiscrim = Load(bcx, lldiscrim_gv);
             Store(bcx, lldiscrim, lldiscrimptr);
             ret lval_no_env(bcx, llenumptr, temporary);
@@ -3339,7 +3329,7 @@ fn trans_landing_pad(bcx: @block_ctxt,
 
 fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
              dest: dest) -> @block_ctxt {
-    let t = node_id_type(bcx.fcx.lcx.ccx, id);
+    let t = node_id_type(bcx.fcx.ccx, id);
     let bcx = bcx;
     let addr = alt dest {
       ignore {
@@ -3728,27 +3718,28 @@ fn load_if_immediate(cx: @block_ctxt, v: ValueRef, t: ty::t) -> ValueRef {
 }
 
 fn trans_log(lvl: @ast::expr, cx: @block_ctxt, e: @ast::expr) -> @block_ctxt {
-    let ccx = bcx_ccx(cx);
-    let lcx = cx.fcx.lcx;
-    let tcx = ccx.tcx;
-    let modname = str::connect(lcx.module_path, "::");
-
+    let ccx = bcx_ccx(cx), tcx = ccx.tcx;
     if ty::type_is_bot(tcx, ty::expr_ty(tcx, lvl)) {
        ret trans_expr(cx, lvl, ignore);
     }
 
-    let global = if lcx.ccx.module_data.contains_key(modname) {
-        lcx.ccx.module_data.get(modname)
+    let modpath = vec::filter(cx.fcx.path, {|e|
+        alt e { path_mod(_) { true } _ { false } }
+    });
+    let modname = path_str(modpath);
+
+    let global = if ccx.module_data.contains_key(modname) {
+        ccx.module_data.get(modname)
     } else {
         let s = link::mangle_internal_name_by_path_and_seq(
-            lcx.ccx, lcx.module_path, "loglevel");
+            ccx, modpath, "loglevel");
         let global = str::as_buf(s, {|buf|
-            llvm::LLVMAddGlobal(lcx.ccx.llmod, T_i32(), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
         });
         llvm::LLVMSetGlobalConstant(global, False);
         llvm::LLVMSetInitializer(global, C_null(T_i32()));
         lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
-        lcx.ccx.module_data.insert(modname, global);
+        ccx.module_data.insert(modname, global);
         global
     };
     let level_cx = new_scope_block_ctxt(cx, "level");
@@ -4033,7 +4024,7 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
                 }
             }
           }
-          ast::decl_item(i) { trans_item(cx.fcx.lcx, *i); }
+          ast::decl_item(i) { trans_item(cx.fcx.ccx, *i); }
         }
       }
       _ { bcx_ccx(cx).sess.unimpl("stmt variant"); }
@@ -4047,9 +4038,8 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
 fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
                   name: str, block_span: option<span>) -> @block_ctxt {
     let s = "";
-    if cx.lcx.ccx.sess.opts.save_temps ||
-           cx.lcx.ccx.sess.opts.debuginfo {
-        s = cx.lcx.ccx.names(name);
+    if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
+        s = cx.ccx.names(name);
     }
     let llbb: BasicBlockRef =
         str::as_buf(s, {|buf| llvm::LLVMAppendBasicBlock(cx.llfn, buf) });
@@ -4278,14 +4268,6 @@ fn trans_block_dps(bcx: @block_ctxt, b: ast::blk, dest: dest)
     ret rv;
 }
 
-fn new_local_ctxt(ccx: @crate_ctxt) -> @local_ctxt {
-    let pth: [str] = [];
-    ret @{path: pth,
-          module_path: [ccx.link_meta.name],
-          ccx: ccx};
-}
-
-
 // Creates the standard quartet of basic blocks: static allocas, copy args,
 // derived tydescs, and dynamic allocas.
 fn mk_standard_basic_blocks(llfn: ValueRef) ->
@@ -4318,8 +4300,8 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
 //  - create_llargs_for_fn_args.
 //  - new_fn_ctxt
 //  - trans_args
-fn new_fn_ctxt_w_id(cx: @local_ctxt, llfndecl: ValueRef,
-                    id: ast::node_id, rstyle: ast::ret_style,
+fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path,
+                    llfndecl: ValueRef, id: ast::node_id,
                     sp: option<span>) -> @fn_ctxt {
     let llbbs = mk_standard_basic_blocks(llfndecl);
     ret @{llfn: llfndecl,
@@ -4339,14 +4321,14 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, llfndecl: ValueRef,
           mutable lltyparams: [],
           derived_tydescs: ty::new_ty_hash(),
           id: id,
-          ret_style: rstyle,
           span: sp,
-          lcx: cx};
+          path: path,
+          ccx: ccx};
 }
 
-fn new_fn_ctxt(cx: @local_ctxt, llfndecl: ValueRef, sp: option<span>)
-    -> @fn_ctxt {
-    ret new_fn_ctxt_w_id(cx, llfndecl, -1, ast::return_val, sp);
+fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef,
+               sp: option<span>) -> @fn_ctxt {
+    ret new_fn_ctxt_w_id(ccx, path, llfndecl, -1, sp);
 }
 
 // NB: must keep 4 fns in sync:
@@ -4472,23 +4454,23 @@ enum self_arg { impl_self(ty::t), no_self, }
 // trans_closure: Builds an LLVM function out of a source function.
 // If the function closes over its environment a closure will be
 // returned.
-fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
+fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
                  body: ast::blk, llfndecl: ValueRef,
                  ty_self: self_arg, ty_params: [ast::ty_param],
                  id: ast::node_id, maybe_load_env: fn(@fn_ctxt)) {
     set_uwtable(llfndecl);
 
     // Set up arguments to the function.
-    let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf, some(body.span));
+    let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, some(body.span));
     create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params);
 
     // Create the first basic block in the function and keep a handle on it to
     //  pass to finish_fn later.
     let bcx = new_top_block_ctxt(fcx, some(body.span));
     let lltop = bcx.llbb;
-    let block_ty = node_id_type(cx.ccx, body.node.id);
+    let block_ty = node_id_type(ccx, body.node.id);
 
-    let arg_tys = arg_tys_of_fn(fcx.lcx.ccx, id);
+    let arg_tys = arg_tys_of_fn(fcx.ccx, id);
     bcx = copy_args_to_allocas(fcx, bcx, decl.inputs, arg_tys);
 
     maybe_load_env(fcx);
@@ -4498,8 +4480,8 @@ fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
     // trans_mod, trans_item, et cetera) and those that do
     // (trans_block, trans_expr, et cetera).
     if option::is_none(body.node.expr) ||
-       ty::type_is_bot(cx.ccx.tcx, block_ty) ||
-       ty::type_is_nil(cx.ccx.tcx, block_ty) {
+       ty::type_is_bot(ccx.tcx, block_ty) ||
+       ty::type_is_nil(ccx.tcx, block_ty) {
         bcx = trans_block(bcx, body);
     } else {
         bcx = trans_block_dps(bcx, body, save_in(fcx.llretptr));
@@ -4514,35 +4496,33 @@ fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
 
 // trans_fn: creates an LLVM function corresponding to a source language
 // function.
-fn trans_fn(cx: @local_ctxt, decl: ast::fn_decl, body: ast::blk,
-            llfndecl: ValueRef, ty_self: self_arg, ty_params: [ast::ty_param],
-            id: ast::node_id) {
-    let do_time = cx.ccx.sess.opts.stats;
+fn trans_fn(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
+            body: ast::blk, llfndecl: ValueRef, ty_self: self_arg,
+            ty_params: [ast::ty_param], id: ast::node_id) {
+    let do_time = ccx.sess.opts.stats;
     let start = if do_time {
                     time::get_time()
                 } else {
                     {sec: 0u32, usec: 0u32}
                 };
     let fcx = option::none;
-    trans_closure(cx, decl, body, llfndecl, ty_self, ty_params, id,
+    trans_closure(ccx, path, decl, body, llfndecl, ty_self, ty_params, id,
                   {|new_fcx| fcx = option::some(new_fcx);});
-    if cx.ccx.sess.opts.extra_debuginfo {
+    if ccx.sess.opts.extra_debuginfo {
         debuginfo::create_function(option::get(fcx));
     }
     if do_time {
         let end = time::get_time();
-        log_fn_time(cx.ccx, str::connect(cx.path, "::"), start, end);
+        log_fn_time(ccx, path_str(path), start, end);
     }
 }
 
-fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
+fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
                   ctor_id: ast::node_id, ty_params: [ast::ty_param]) {
-    let ccx = cx.ccx;
-
     // Create a function for the constructor
     let llctor_decl = ccx.item_ids.get(ctor_id);
-    let fcx = new_fn_ctxt(cx, llctor_decl, none);
-    let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
+    let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, none);
+    let ret_t = ty::ret_ty_of_fn(ccx.tcx, ctor_id);
     create_llargs_for_fn_args(fcx, no_self, dtor.inputs, ty_params);
     let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
@@ -4574,25 +4554,21 @@ fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
 }
 
 
-fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
-                     variant: ast::variant, disr: int, is_degen: bool,
-                     ty_params: [ast::ty_param]) {
-    let ccx = cx.ccx;
-
-    if vec::len::<ast::variant_arg>(variant.node.args) == 0u {
+fn trans_enum_variant(ccx: @crate_ctxt,
+                      enum_id: ast::node_id,
+                      variant: ast::variant, disr: int, is_degen: bool,
+                      ty_params: [ast::ty_param]) {
+    if vec::len(variant.node.args) == 0u {
         ret; // nullary constructors are just constants
-
     }
-    // Translate variant arguments to function arguments.
 
-    let fn_args: [ast::arg] = [];
-    let i = 0u;
-    for varg: ast::variant_arg in variant.node.args {
-        fn_args +=
-            [{mode: ast::by_copy,
-              ty: varg.ty,
-              ident: "arg" + uint::to_str(i, 10u),
-              id: varg.id}];
+    // Translate variant arguments to function arguments.
+    let fn_args = [], i = 0u;
+    for varg in variant.node.args {
+        fn_args += [{mode: ast::by_copy,
+                     ty: varg.ty,
+                     ident: "arg" + uint::to_str(i, 10u),
+                     id: varg.id}];
     }
     assert (ccx.item_ids.contains_key(variant.node.id));
     let llfndecl: ValueRef;
@@ -4600,16 +4576,15 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
       some(x) { llfndecl = x; }
       _ {
         ccx.sess.span_fatal(variant.span,
-                               "unbound variant id in trans_enum_variant");
+                            "unbound variant id in trans_enum_variant");
       }
     }
-    let fcx = new_fn_ctxt(cx, llfndecl, none);
+    let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id, none);
     create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
-    let ty_param_substs: [ty::t] = [];
-    i = 0u;
+    let ty_param_substs = [], i = 0u;
     for tp: ast::ty_param in ty_params {
         ty_param_substs += [ty::mk_param(ccx.tcx, i,
-                                         ast_util::local_def(tp.id))];
+                                         local_def(tp.id))];
         i += 1u;
     }
     let arg_tys = arg_tys_of_fn(ccx, variant.node.id);
@@ -4618,19 +4593,18 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
     bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys);
 
     // Cast the enum to a type we can GEP into.
-    let llblobptr =
-        if is_degen {
-            fcx.llretptr
-        } else {
-            let llenumptr =
-                PointerCast(bcx, fcx.llretptr, T_opaque_enum_ptr(ccx));
-            let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
-            Store(bcx, C_int(ccx, disr), lldiscrimptr);
-            GEPi(bcx, llenumptr, [0, 1])
-        };
-    i = 0u;
-    let t_id = ast_util::local_def(enum_id);
-    let v_id = ast_util::local_def(variant.node.id);
+    let llblobptr = if is_degen {
+        fcx.llretptr
+    } else {
+        let llenumptr =
+            PointerCast(bcx, fcx.llretptr, T_opaque_enum_ptr(ccx));
+        let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
+        Store(bcx, C_int(ccx, disr), lldiscrimptr);
+        GEPi(bcx, llenumptr, [0, 1])
+    };
+    let i = 0u;
+    let t_id = local_def(enum_id);
+    let v_id = local_def(variant.node.id);
     for va: ast::variant_arg in variant.node.args {
         check (valid_variant_index(i, bcx, t_id, v_id));
         let rslt = GEP_enum(bcx, llblobptr, t_id, v_id, ty_param_substs, i);
@@ -4813,14 +4787,13 @@ fn c_stack_tys(ccx: @crate_ctxt,
 // stack pointer appropriately to avoid a round of copies.  (In fact, the shim
 // function itself is unnecessary). We used to do this, in fact, and will
 // perhaps do so in the future.
-fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
-                    abi: ast::native_abi) {
-    fn build_shim_fn(lcx: @local_ctxt,
+fn trans_native_mod(ccx: @crate_ctxt,
+                    native_mod: ast::native_mod, abi: ast::native_abi) {
+    fn build_shim_fn(ccx: @crate_ctxt,
                      native_item: @ast::native_item,
                      tys: @c_stack_tys,
                      cc: lib::llvm::CallConv) -> ValueRef {
         let lname = link_name(native_item);
-        let ccx = lcx_ccx(lcx);
 
         // Declare the "prototype" for the base function F:
         let llbasefn = decl_fn(ccx.llmod, lname, cc, tys.base_fn_ty);
@@ -4831,7 +4804,7 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
             ccx.llmod, shim_name, tys.shim_fn_ty);
 
         // Declare the body of the shim function:
-        let fcx = new_fn_ctxt(lcx, llshimfn, none);
+        let fcx = new_fn_ctxt(ccx, [], llshimfn, none);
         let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
         let llargbundle = llvm::LLVMGetParam(llshimfn, 0 as c_uint);
@@ -4862,13 +4835,12 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
         ret llshimfn;
     }
 
-    fn build_wrap_fn(lcx: @local_ctxt,
+    fn build_wrap_fn(ccx: @crate_ctxt,
                      tys: @c_stack_tys,
                      num_tps: uint,
                      llshimfn: ValueRef,
                      llwrapfn: ValueRef) {
-        let ccx = lcx_ccx(lcx);
-        let fcx = new_fn_ctxt(lcx, llwrapfn, none);
+        let fcx = new_fn_ctxt(ccx, [], llwrapfn, none);
         let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
 
@@ -4894,7 +4866,6 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
         finish_fn(fcx, lltop);
     }
 
-    let ccx = lcx_ccx(lcx);
     let cc = lib::llvm::CCallConv;
     alt abi {
       ast::native_abi_rust_intrinsic { ret; }
@@ -4909,10 +4880,9 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
           let tys = c_stack_tys(ccx, id);
           alt ccx.item_ids.find(id) {
             some(llwrapfn) {
-              let llshimfn = build_shim_fn(lcx, native_item, tys, cc);
-              build_wrap_fn(lcx, tys, vec::len(tps), llshimfn, 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_fatal(
                   native_item.span,
@@ -4924,63 +4894,61 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
     }
 }
 
-fn trans_item(cx: @local_ctxt, item: ast::item) {
+fn trans_item(ccx: @crate_ctxt, item: ast::item) {
+    let path = alt ccx.tcx.items.get(item.id) {
+      ast_map::node_item(_, p) { p }
+      _ { fail; }
+    };
     alt item.node {
       ast::item_fn(decl, tps, body) {
-        let sub_cx = extend_path(cx, item.ident);
-        alt cx.ccx.item_ids.find(item.id) {
+        alt ccx.item_ids.find(item.id) {
           some(llfndecl) {
-            trans_fn(sub_cx, decl, body, llfndecl, no_self, tps,
-                     item.id);
+            trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
+                     llfndecl, no_self, tps, item.id);
           }
           _ {
-            cx.ccx.sess.span_fatal(item.span,
-                                   "unbound function item in trans_item");
+            ccx.sess.span_fatal(item.span,
+                                "unbound function item in trans_item");
           }
         }
       }
       ast::item_impl(tps, _, _, ms) {
-        impl::trans_impl(cx, item.ident, ms, item.id, tps);
+        impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
       }
       ast::item_res(decl, tps, body, dtor_id, ctor_id) {
-        trans_res_ctor(cx, decl, ctor_id, tps);
+        trans_res_ctor(ccx, *path, decl, ctor_id, tps);
 
         // Create a function for the destructor
-        alt cx.ccx.item_ids.find(item.id) {
+        alt ccx.item_ids.find(item.id) {
           some(lldtor_decl) {
-            trans_fn(cx, decl, body, lldtor_decl, no_self,
-                     tps, dtor_id);
+            trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
+                     lldtor_decl, no_self, tps, dtor_id);
           }
           _ {
-            cx.ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
+            ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
           }
         }
       }
       ast::item_mod(m) {
-        let sub_cx =
-            @{path: cx.path + [item.ident],
-              module_path: cx.module_path + [item.ident] with *cx};
-        trans_mod(sub_cx, m);
+        trans_mod(ccx, m);
       }
       ast::item_enum(variants, tps) {
-        let sub_cx = extend_path(cx, item.ident);
         let degen = vec::len(variants) == 1u;
-        let vi = ty::enum_variants(cx.ccx.tcx, {crate: ast::local_crate,
-                                               node: item.id});
+        let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
         let i = 0;
         for variant: ast::variant in variants {
-            trans_enum_variant(sub_cx, item.id, variant,
-                              vi[i].disr_val, degen, tps);
+            trans_enum_variant(ccx, item.id, variant,
+                               vi[i].disr_val, degen, tps);
             i += 1;
         }
       }
-      ast::item_const(_, expr) { trans_const(cx.ccx, expr, item.id); }
+      ast::item_const(_, expr) { trans_const(ccx, expr, item.id); }
       ast::item_native_mod(native_mod) {
         let abi = alt attr::native_abi(item.attrs) {
           either::right(abi_) { abi_ }
-          either::left(msg) { cx.ccx.sess.span_fatal(item.span, msg) }
+          either::left(msg) { ccx.sess.span_fatal(item.span, msg) }
         };
-        trans_native_mod(cx, native_mod, abi);
+        trans_native_mod(ccx, native_mod, abi);
       }
       _ {/* fall through */ }
     }
@@ -4991,8 +4959,8 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
 // separate modules in the compiled program.  That's because modules exist
 // only as a convenience for humans working with the code, to organize names
 // and control visibility.
-fn trans_mod(cx: @local_ctxt, m: ast::_mod) {
-    for item: @ast::item in m.items { trans_item(cx, *item); }
+fn trans_mod(ccx: @crate_ctxt, m: ast::_mod) {
+    for item in m.items { trans_item(ccx, *item); }
 }
 
 fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
@@ -5001,7 +4969,7 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
     ret struct_elt(llpairty, 0u);
 }
 
-fn register_fn(ccx: @crate_ctxt, sp: span, path: [str], flav: str,
+fn register_fn(ccx: @crate_ctxt, sp: span, path: path, flav: str,
                ty_params: [ast::ty_param], node_id: ast::node_id) {
     // FIXME: pull this out
     let t = node_id_type(ccx, node_id);
@@ -5013,11 +4981,10 @@ fn param_bounds(ccx: @crate_ctxt, tp: ast::ty_param) -> ty::param_bounds {
     ccx.tcx.ty_param_bounds.get(tp.id)
 }
 
-fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
+fn register_fn_full(ccx: @crate_ctxt, sp: span, path: path, _flav: str,
                     tps: [ast::ty_param], node_id: ast::node_id,
                     node_type: ty::t)
     : returns_non_ty_var(ccx, node_type) {
-    let path = path;
     let llfty = type_of_fn_from_ty(ccx, node_type,
                                    vec::map(tps, {|p| param_bounds(ccx, p)}));
     let ps: str = mangle_exported_name(ccx, path, node_type);
@@ -5025,7 +4992,7 @@ fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
     ccx.item_ids.insert(node_id, llfn);
     ccx.item_symbols.insert(node_id, ps);
 
-    let is_main: bool = is_main_name(path) && !ccx.sess.building_library;
+    let is_main = is_main_name(path) && !ccx.sess.building_library;
     if is_main { create_main_wrapper(ccx, sp, llfn, node_type); }
 }
 
@@ -5061,7 +5028,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
         let llfdecl = decl_fn(ccx.llmod, "_rust_main",
                               lib::llvm::CCallConv, llfty);
 
-        let fcx = new_fn_ctxt(new_local_ctxt(ccx), llfdecl, none);
+        let fcx = new_fn_ctxt(ccx, [], llfdecl, none);
 
         let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
@@ -5115,9 +5082,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
 // on the stack).
 fn create_real_fn_pair(cx: @block_ctxt, llfnty: TypeRef, llfn: ValueRef,
                        llenvptr: ValueRef) -> ValueRef {
-    let lcx = cx.fcx.lcx;
-
-    let pair = alloca(cx, T_fn_pair(lcx.ccx, llfnty));
+    let pair = alloca(cx, T_fn_pair(bcx_ccx(cx), llfnty));
     fill_fn_pair(cx, pair, llfn, llenvptr);
     ret pair;
 }
@@ -5137,9 +5102,10 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     let count;
     let native_item =
         // invariant?!
-        alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i }
-         _ { cx.sess.bug("native_fn_ty_param_count\
-                         given a non-native item"); } };
+        alt cx.ast_map.find(id) {
+          some(ast_map::node_native_item(i, _)) { i }
+         _ { cx.sess.bug("native_fn_ty_param_count \
+                          given a non-native item"); } };
     alt native_item.node {
       ast::native_item_fn(_, tps) {
         count = vec::len::<ast::ty_param>(tps);
@@ -5177,9 +5143,7 @@ fn link_name(i: @ast::native_item) -> str {
 
 fn collect_native_item(ccx: @crate_ctxt,
                        abi: @mutable option<ast::native_abi>,
-                       i: @ast::native_item,
-                       &&pt: [str],
-                       _v: vt<[str]>) {
+                       i: @ast::native_item) {
     alt i.node {
       ast::native_item_fn(_, tps) {
         let id = i.id;
@@ -5217,8 +5181,10 @@ fn collect_native_item(ccx: @crate_ctxt,
             // For true external functions: create a rust wrapper
             // and link to that.  The rust wrapper will handle
             // switching to the C stack.
-            let new_pt = pt + [i.ident];
-            register_fn(ccx, i.span, new_pt, "native fn", tps, i.id);
+            let path = *alt ccx.tcx.items.get(i.id) {
+              ast_map::node_native_item(_, p) { p } _ { fail; }
+            } + [path_name(i.ident)];
+            register_fn(ccx, i.span, path, "native fn", tps, i.id);
           }
         }
       }
@@ -5226,15 +5192,20 @@ fn collect_native_item(ccx: @crate_ctxt,
     }
 }
 
+fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
+    *alt ccx.tcx.items.get(i.id) {
+      ast_map::node_item(_, p) { p } _ { fail; }
+    } + [path_name(i.ident)]
+}
+
 fn collect_item(ccx: @crate_ctxt, abi: @mutable option<ast::native_abi>,
-                i: @ast::item, &&pt: [str], v: vt<[str]>) {
-    let new_pt = pt + [i.ident];
+                i: @ast::item) {
+    let my_path = item_path(ccx, i);
     alt i.node {
       ast::item_const(_, _) {
         let typ = node_id_type(ccx, i.id);
-        let s =
-            mangle_exported_name(ccx, pt + [i.ident],
-                                 node_id_type(ccx, i.id));
+        let s = mangle_exported_name(ccx, my_path,
+                                     node_id_type(ccx, i.id));
         // FIXME: Could follow from a constraint on types of const
         // items
         let g = str::as_buf(s, {|buf|
@@ -5248,23 +5219,23 @@ fn collect_item(ccx: @crate_ctxt, abi: @mutable option<ast::native_abi>,
         // 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_);
-          }
+          either::right(abi_) { *abi = option::some(abi_); }
         }
       }
       ast::item_fn(_, tps, _) {
-        register_fn(ccx, i.span, new_pt, "fn", tps, i.id);
+        register_fn(ccx, i.span, my_path, "fn", tps,
+                    i.id);
       }
       ast::item_impl(tps, _, _, methods) {
-        let name = i.ident + int::str(i.id);
+        let path = my_path + [path_name(int::str(i.id))];
         for m in methods {
-            register_fn(ccx, i.span, pt + [name, m.ident],
+            register_fn(ccx, i.span,
+                        path + [path_name(m.ident)],
                         "impl_method", tps + m.tps, m.id);
         }
       }
       ast::item_res(_, tps, _, dtor_id, ctor_id) {
-        register_fn(ccx, i.span, new_pt, "res_ctor", tps, ctor_id);
+        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
@@ -5272,42 +5243,41 @@ fn collect_item(ccx: @crate_ctxt, abi: @mutable option<ast::native_abi>,
         let t = node_id_type(ccx, dtor_id);
         // FIXME: how to get rid of this check?
         check returns_non_ty_var(ccx, t);
-        register_fn_full(ccx, i.span, new_pt, "res_dtor", tps, i.id, t);
+        register_fn_full(ccx, i.span, my_path + [path_name("dtor")],
+                         "res_dtor", tps, i.id, t);
       }
       ast::item_enum(variants, tps) {
         for variant in variants {
             if vec::len(variant.node.args) != 0u {
-                register_fn(ccx, i.span, new_pt + [variant.node.name],
+                register_fn(ccx, i.span,
+                            my_path + [path_name(variant.node.name)],
                             "enum", tps, variant.node.id);
             }
         }
       }
       _ { }
     }
-    visit::visit_item(i, new_pt, v);
 }
 
 fn collect_items(ccx: @crate_ctxt, crate: @ast::crate) {
     let abi = @mutable none::<ast::native_abi>;
-    visit::visit_crate(*crate, [], visit::mk_vt(@{
-        visit_native_item: bind collect_native_item(ccx, abi, _, _, _),
-        visit_item: bind collect_item(ccx, abi, _, _, _)
-        with *visit::default_visitor()
+    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, &&pt: [str],
-                  v: vt<[str]>) {
-    let new_pt = pt + [it.ident];
-    visit::visit_item(it, new_pt, v);
+fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
     alt it.node {
       ast::item_enum(variants, _) {
         let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
-                                            node: it.id});
-        let i = 0;
+                                             node: it.id});
+        let i = 0, path = item_path(ccx, it);
         for variant in variants {
-            let p = new_pt + [variant.node.name, "discrim"];
+            let p = path + [path_name(variant.node.name),
+                            path_name("discrim")];
             let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
             let disr_val = vi[i].disr_val;
             let discrim_gvar = str::as_buf(s, {|buf|
@@ -5316,27 +5286,27 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
             llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
             llvm::LLVMSetGlobalConstant(discrim_gvar, True);
             ccx.discrims.insert(
-                ast_util::local_def(variant.node.id), discrim_gvar);
+                local_def(variant.node.id), discrim_gvar);
             ccx.discrim_symbols.insert(variant.node.id, s);
             i += 1;
         }
       }
       ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) {
         let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id));
-        impl::trans_impl_vtable(ccx, pt, i_did, ms, tps, it);
+        impl::trans_impl_vtable(ccx, item_path(ccx, it), i_did, ms, tps, it);
       }
       ast::item_iface(_, _) {
-        impl::trans_iface_vtable(ccx, pt, it);
+        impl::trans_iface_vtable(ccx, item_path(ccx, it), it);
       }
       _ { }
     }
 }
 
 fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) {
-    let visitor =
-        @{visit_item: bind trans_constant(ccx, _, _, _)
-             with *visit::default_visitor()};
-    visit::visit_crate(*crate, [], visit::mk_vt(visitor));
+    visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
+        visit_item: bind trans_constant(ccx, _)
+        with *visit::default_simple_visitor()
+    }));
 }
 
 fn vp2i(cx: @block_ctxt, v: ValueRef) -> ValueRef {
@@ -5597,17 +5567,16 @@ 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};
-    let cx = new_local_ctxt(ccx);
     collect_items(ccx, crate);
     trans_constants(ccx, crate);
-    trans_mod(cx, crate.node.module);
+    trans_mod(ccx, crate.node.module);
     fill_crate_map(ccx, crate_map);
     emit_tydescs(ccx);
     shape::gen_shape_tables(ccx);
     write_abi_version(ccx);
 
     // Translate the metadata.
-    write_metadata(cx.ccx, crate);
+    write_metadata(ccx, crate);
     if ccx.sess.opts.stats {
         #error("--- trans stats ---");
         #error("n_static_tydescs: %u", ccx.stats.n_static_tydescs);
diff --git a/src/comp/middle/trans/build.rs b/src/comp/middle/trans/build.rs
index a9bd2a33bfb..dd3bf78f46d 100644
--- a/src/comp/middle/trans/build.rs
+++ b/src/comp/middle/trans/build.rs
@@ -11,7 +11,7 @@ import common::{block_ctxt, T_ptr, T_nil, T_i8, T_i1, T_void,
                 T_fn, val_ty, bcx_ccx, C_i32, val_str};
 
 fn B(cx: @block_ctxt) -> BuilderRef {
-    let b = *cx.fcx.lcx.ccx.builder;
+    let b = *cx.fcx.ccx.builder;
     llvm::LLVMPositionBuilderAtEnd(b, cx.llbb);
     ret b;
 }
@@ -312,7 +312,7 @@ fn Free(cx: @block_ctxt, PointerVal: ValueRef) {
 }
 
 fn Load(cx: @block_ctxt, PointerVal: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     if cx.unreachable {
         let ty = val_ty(PointerVal);
         let eltty = if llvm::LLVMGetTypeKind(ty) == 11 as c_int {
@@ -511,7 +511,7 @@ fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
 }
 
 fn _UndefReturn(cx: @block_ctxt, Fn: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     let ty = val_ty(Fn);
     let retty = if llvm::LLVMGetTypeKind(ty) == 8 as c_int {
         llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
@@ -625,7 +625,7 @@ fn IsNotNull(cx: @block_ctxt, Val: ValueRef) -> ValueRef {
 }
 
 fn PtrDiff(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     if cx.unreachable { ret llvm::LLVMGetUndef(ccx.int_type); }
     ret llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
 }
diff --git a/src/comp/middle/trans/closure.rs b/src/comp/middle/trans/closure.rs
index d051662a14e..4b4cde89486 100644
--- a/src/comp/middle/trans/closure.rs
+++ b/src/comp/middle/trans/closure.rs
@@ -16,6 +16,7 @@ import back::link::{
     mangle_internal_name_by_path_and_seq};
 import util::ppaux::ty_to_str;
 import shape::{size_of};
+import ast_map::{path, path_mod, path_name};
 
 // ___Good to know (tm)__________________________________________________
 //
@@ -458,16 +459,16 @@ fn trans_expr_fn(bcx: @block_ctxt,
     let ccx = bcx_ccx(bcx), bcx = bcx;
     let fty = node_id_type(ccx, id);
     let llfnty = type_of_fn_from_ty(ccx, fty, []);
-    let sub_cx = extend_path(bcx.fcx.lcx, ccx.names("anon"));
-    let s = mangle_internal_name_by_path(ccx, sub_cx.path);
+    let sub_path = bcx.fcx.path + [path_name("anon")];
+    let s = mangle_internal_name_by_path(ccx, sub_path);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
-    register_fn(ccx, sp, sub_cx.path, "anon fn", [], id);
+    register_fn(ccx, sp, sub_path, "anon fn", [], id);
 
     let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
         let cap_vars = capture::compute_capture_vars(
             ccx.tcx, id, proto, cap_clause);
         let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck);
-        trans_closure(sub_cx, decl, body, llfn, no_self, [], id, {|fcx|
+        trans_closure(ccx, sub_path, decl, body, llfn, no_self, [], id, {|fcx|
             load_environment(bcx, fcx, cdata_ty, cap_vars, ck);
         });
         llbox
@@ -479,7 +480,8 @@ fn trans_expr_fn(bcx: @block_ctxt,
       ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
       ast::proto_bare {
         let closure = C_null(T_opaque_box_ptr(ccx));
-        trans_closure(sub_cx, decl, body, llfn, no_self, [], id, {|_fcx|});
+        trans_closure(ccx, sub_path, decl, body, llfn, no_self, [], id,
+                      {|_fcx|});
         closure
       }
     };
@@ -569,9 +571,9 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
         ty::ck_box);
 
     // Make thunk
-    let llthunk =
-        trans_bind_thunk(cx.fcx.lcx, pair_ty, outgoing_fty_real, args,
-                         cdata_ty, *param_bounds, target_res);
+    let llthunk = trans_bind_thunk(
+        cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty_real, args,
+        cdata_ty, *param_bounds, target_res);
 
     // Fill the function pair
     fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
@@ -727,7 +729,8 @@ fn make_opaque_cbox_free_glue(
 }
 
 // pth is cx.path
-fn trans_bind_thunk(cx: @local_ctxt,
+fn trans_bind_thunk(ccx: @crate_ctxt,
+                    path: path,
                     incoming_fty: ty::t,
                     outgoing_fty: ty::t,
                     args: [option<@ast::expr>],
@@ -743,8 +746,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
       type_has_static_size(ccx, incoming_fty) ->
     */
     // but since we don't, we have to do the checks at the beginning.
-    let ccx = cx.ccx;
-    let tcx = ccx_tcx(ccx);
+    let tcx = ccx.tcx;
     check type_has_static_size(ccx, incoming_fty);
 
     #debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
@@ -776,13 +778,13 @@ fn trans_bind_thunk(cx: @local_ctxt,
     // construct and return that thunk.
 
     // Give the thunk a name, type, and value.
-    let s: str = mangle_internal_name_by_path_and_seq(ccx, cx.path, "thunk");
-    let llthunk_ty: TypeRef = get_pair_fn_ty(type_of(ccx, incoming_fty));
-    let llthunk: ValueRef = decl_internal_cdecl_fn(ccx.llmod, s, llthunk_ty);
+    let s = mangle_internal_name_by_path_and_seq(ccx, path, "thunk");
+    let llthunk_ty = get_pair_fn_ty(type_of(ccx, incoming_fty));
+    let llthunk = decl_internal_cdecl_fn(ccx.llmod, s, llthunk_ty);
 
     // Create a new function context and block context for the thunk, and hold
     // onto a pointer to the first block in the function for later use.
-    let fcx = new_fn_ctxt(cx, llthunk, none);
+    let fcx = new_fn_ctxt(ccx, path, llthunk, none);
     let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
     // Since we might need to construct derived tydescs that depend on
@@ -828,15 +830,14 @@ fn trans_bind_thunk(cx: @local_ctxt,
 
     // Get f's return type, which will also be the return type of the entire
     // bind expression.
-    let outgoing_ret_ty = ty::ty_fn_ret(cx.ccx.tcx, outgoing_fty);
+    let outgoing_ret_ty = ty::ty_fn_ret(ccx.tcx, outgoing_fty);
 
     // Get the types of the arguments to f.
-    let outgoing_args = ty::ty_fn_args(cx.ccx.tcx, outgoing_fty);
+    let outgoing_args = ty::ty_fn_args(ccx.tcx, outgoing_fty);
 
     // The 'llretptr' that will arrive in the thunk we're creating also needs
     // to be the correct type.  Cast it to f's return type, if necessary.
     let llretptr = fcx.llretptr;
-    let ccx = cx.ccx;
     if ty::type_contains_params(ccx.tcx, outgoing_ret_ty) {
         check non_ty_var(ccx, outgoing_ret_ty);
         let llretty = type_of_inner(ccx, outgoing_ret_ty);
@@ -879,7 +880,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
     let b: int = starting_idx;
     let outgoing_arg_index: uint = 0u;
     let llout_arg_tys: [TypeRef] =
-        type_of_explicit_args(cx.ccx, outgoing_args);
+        type_of_explicit_args(ccx, outgoing_args);
     for arg: option<@ast::expr> in args {
         let out_arg = outgoing_args[outgoing_arg_index];
         let llout_arg_ty = llout_arg_tys[outgoing_arg_index];
@@ -903,7 +904,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
             }
             // If the type is parameterized, then we need to cast the
             // type we actually have to the parameterized out type.
-            if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) {
+            if ty::type_contains_params(ccx.tcx, out_arg.ty) {
                 val = PointerCast(bcx, val, llout_arg_ty);
             }
             llargs += [val];
@@ -913,7 +914,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
           // Arg will be provided when the thunk is invoked.
           none {
             let arg: ValueRef = llvm::LLVMGetParam(llthunk, a as c_uint);
-            if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) {
+            if ty::type_contains_params(ccx.tcx, out_arg.ty) {
                 arg = PointerCast(bcx, arg, llout_arg_ty);
             }
             llargs += [arg];
@@ -927,8 +928,6 @@ fn trans_bind_thunk(cx: @local_ctxt,
     // This is necessary because the type of the function that we have
     // in the closure does not know how many type descriptors the function
     // needs to take.
-    let ccx = bcx_ccx(bcx);
-
     let lltargetty =
         type_of_fn_from_ty(ccx, outgoing_fty, param_bounds);
     lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
diff --git a/src/comp/middle/trans/common.rs b/src/comp/middle/trans/common.rs
index 20f32954438..1b7b73420a4 100644
--- a/src/comp/middle/trans/common.rs
+++ b/src/comp/middle/trans/common.rs
@@ -19,7 +19,8 @@ import lib::llvm::{llvm, target_data, type_names, associate_type,
                    name_has_type};
 import lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
 import lib::llvm::{True, False, Bool};
-import metadata::{csearch};
+import metadata::csearch;
+import ast_map::path;
 
 // FIXME: These should probably be pulled in here too.
 import base::{type_of_fn, drop_ty};
@@ -124,11 +125,6 @@ type crate_ctxt =
      dbg_cx: option<@debuginfo::debug_ctxt>,
      mutable do_not_commit_warning_issued: bool};
 
-type local_ctxt =
-    {path: [str],
-     module_path: [str],
-     ccx: @crate_ctxt};
-
 // Types used for llself.
 type val_self_pair = {v: ValueRef, t: ty::t};
 
@@ -239,9 +235,9 @@ type fn_ctxt =
      mutable lltyparams: [fn_ty_param],
      derived_tydescs: hashmap<ty::t, derived_tydesc_info>,
      id: ast::node_id,
-     ret_style: ast::ret_style,
      span: option<span>,
-     lcx: @local_ctxt};
+     path: path,
+     ccx: @crate_ctxt};
 
 fn warn_not_to_commit(ccx: @crate_ctxt, msg: str) {
     if !ccx.do_not_commit_warning_issued {
@@ -392,10 +388,6 @@ enum block_parent { parent_none, parent_some(@block_ctxt), }
 type result = {bcx: @block_ctxt, val: ValueRef};
 type result_t = {bcx: @block_ctxt, val: ValueRef, ty: ty::t};
 
-fn extend_path(cx: @local_ctxt, name: str) -> @local_ctxt {
-    ret @{path: cx.path + [name] with *cx};
-}
-
 fn rslt(bcx: @block_ctxt, val: ValueRef) -> result {
     {bcx: bcx, val: val}
 }
@@ -430,13 +422,11 @@ fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
 // Accessors
 // TODO: When we have overloading, simplify these names!
 
-pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
-pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
-pure fn bcx_lcx(bcx: @block_ctxt) -> @local_ctxt { ret bcx.fcx.lcx; }
+pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.ccx.tcx; }
+pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.ccx; }
 pure fn bcx_fcx(bcx: @block_ctxt) -> @fn_ctxt { ret bcx.fcx; }
-pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.lcx.ccx; }
-pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.lcx.ccx.tcx; }
-pure fn lcx_ccx(lcx: @local_ctxt) -> @crate_ctxt { ret lcx.ccx; }
+pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.ccx; }
+pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.ccx.tcx; }
 pure fn ccx_tcx(ccx: @crate_ctxt) -> ty::ctxt { ret ccx.tcx; }
 
 // LLVM type constructors.
@@ -943,6 +933,18 @@ fn align_to(cx: @block_ctxt, off: ValueRef, align: ValueRef) -> ValueRef {
     ret build::And(cx, bumped, build::Not(cx, mask));
 }
 
+fn path_str(p: path) -> str {
+    let r = "", first = true;
+    for e in p {
+        alt e { ast_map::path_name(s) | ast_map::path_mod(s) {
+          if first { first = false; }
+          else { r += "::"; }
+          r += s;
+        } }
+    }
+    r
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/middle/trans/impl.rs b/src/comp/middle/trans/impl.rs
index 9988508903c..531af92a93d 100644
--- a/src/comp/middle/trans/impl.rs
+++ b/src/comp/middle/trans/impl.rs
@@ -10,6 +10,7 @@ import back::{link, abi};
 import lib::llvm::llvm;
 import lib::llvm::{ValueRef, TypeRef};
 import lib::llvm::llvm::LLVMGetParam;
+import ast_map::{path, path_mod, path_name};
 
 // Translation functionality related to impls and ifaces
 //
@@ -41,18 +42,19 @@ import lib::llvm::llvm::LLVMGetParam;
 // annotates notes with information about the methods and dicts that
 // are referenced (ccx.method_map and ccx.dict_map).
 
-fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
-              id: ast::node_id, tps: [ast::ty_param]) {
-    let sub_cx = extend_path(cx, name);
+fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
+              methods: [@ast::method], id: ast::node_id,
+              tps: [ast::ty_param]) {
+    let sub_path = path + [path_name(name)];
     for m in methods {
-        alt cx.ccx.item_ids.find(m.id) {
+        alt ccx.item_ids.find(m.id) {
           some(llfn) {
-            trans_fn(extend_path(sub_cx, m.ident), m.decl, m.body,
-                     llfn, impl_self(ty::node_id_to_type(cx.ccx.tcx, id)),
+            trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
+                     llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
                      tps + m.tps, m.id);
           }
           _ {
-            cx.ccx.tcx.sess.bug("Unbound id in trans_impl");
+            ccx.tcx.sess.bug("Unbound id in trans_impl");
           }
         }
     }
@@ -180,13 +182,12 @@ fn trans_vtable(ccx: @crate_ctxt, id: ast::node_id, name: str,
     ccx.item_symbols.insert(id, name);
 }
 
-fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident], llfty: TypeRef,
+fn trans_wrapper(ccx: @crate_ctxt, pt: path, llfty: TypeRef,
                  fill: fn(ValueRef, @block_ctxt) -> @block_ctxt)
     -> ValueRef {
-    let lcx = @{path: pt, module_path: [], ccx: ccx};
     let name = link::mangle_internal_name_by_path(ccx, pt);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfty);
-    let fcx = new_fn_ctxt(lcx, llfn, none);
+    let fcx = new_fn_ctxt(ccx, [], llfn, none);
     let bcx = new_top_block_ctxt(fcx, none), lltop = bcx.llbb;
     let bcx = fill(llfn, bcx);
     build_return(bcx);
@@ -194,7 +195,7 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident], llfty: TypeRef,
     ret llfn;
 }
 
-fn trans_impl_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
+fn trans_impl_wrapper(ccx: @crate_ctxt, pt: path,
                       extra_tps: [ty::param_bounds], real_fn: ValueRef)
     -> ValueRef {
     let {inputs: real_args, output: real_ret} =
@@ -238,16 +239,18 @@ fn trans_impl_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
     })
 }
 
-fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
+fn trans_impl_vtable(ccx: @crate_ctxt, pt: path,
                      iface_id: ast::def_id, ms: [@ast::method],
                      tps: [ast::ty_param], it: @ast::item) {
-    let new_pt = pt + [it.ident + int::str(it.id), "wrap"];
+    let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id)),
+                       path_name("wrap")];
     let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
     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 + [m.ident], extra_tps, target)
+            trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)], extra_tps,
+                               target)
           }
           _ {
             ccx.tcx.sess.span_bug(it.span, "No matching method \
@@ -255,11 +258,12 @@ fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
           }
         }
     });
-    let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
+    let s = link::mangle_internal_name_by_path(
+        ccx, new_pt + [path_name("!vtable")]);
     trans_vtable(ccx, it.id, s, ptrs);
 }
 
-fn trans_iface_wrapper(ccx: @crate_ctxt, pt: [ast::ident], m: ty::method,
+fn trans_iface_wrapper(ccx: @crate_ctxt, pt: path, m: ty::method,
                        n: uint) -> ValueRef {
     let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()), m);
     trans_wrapper(ccx, pt, llfty, {|llfn, bcx|
@@ -287,15 +291,16 @@ fn trans_iface_wrapper(ccx: @crate_ctxt, pt: [ast::ident], m: ty::method,
     })
 }
 
-fn trans_iface_vtable(ccx: @crate_ctxt, pt: [ast::ident], it: @ast::item) {
-    let new_pt = pt + [it.ident + int::str(it.id)];
+fn trans_iface_vtable(ccx: @crate_ctxt, pt: path, it: @ast::item) {
+    let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id))];
     let i_did = ast_util::local_def(it.id), i = 0u;
     let ptrs = vec::map(*ty::iface_methods(ccx.tcx, i_did), {|m|
-        let w = trans_iface_wrapper(ccx, new_pt + [m.ident], m, i);
+        let w = trans_iface_wrapper(ccx, new_pt + [path_name(m.ident)], m, i);
         i += 1u;
         w
     });
-    let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
+    let s = link::mangle_internal_name_by_path(
+        ccx, new_pt + [path_name("!vtable")]);
     trans_vtable(ccx, it.id, s, ptrs);
 }
 
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 013ffd56867..7197ed26bad 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -2531,7 +2531,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
         // check the disr_expr if it exists), this code should likely be
         // moved there to avoid having to call eval_const_expr twice.
         alt cx.items.get(id.node) {
-          ast_map::node_item(@{node: ast::item_enum(variants, _), _}) {
+          ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) {
             let disr_val = -1;
             @vec::map(variants, {|variant|
                 let ctor_ty = node_id_to_type(cx, variant.node.id);
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index b7d35128cbf..c073b969d88 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -245,10 +245,10 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
             if id.crate != ast::local_crate { csearch::get_type(tcx, id) }
             else {
                 alt tcx.items.find(id.node) {
-                  some(ast_map::node_item(item)) {
+                  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)
                   }
                   _ {
@@ -1415,7 +1415,7 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
     if did.crate == ast::local_crate {
         alt tcx.items.get(did.node) {
           ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
-                               _}) {
+                               _}, _) {
             {n_tps: vec::len(ts), ty: ast_ty_to_ty(tcx, m_check, st)}
           }
           an_item {
@@ -1484,7 +1484,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
     fn ty_from_did(tcx: ty::ctxt, did: ast::def_id) -> ty::t {
         if did.crate == ast::local_crate {
             alt tcx.items.get(did.node) {
-              ast_map::node_method(m) {
+              ast_map::node_method(m, _) {
                 let mt = ty_of_method(tcx, m_check, m);
                 ty::mk_fn(tcx, mt.fty)
               }
diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs
index 172afa35fe9..b96165fb473 100644
--- a/src/comp/util/common.rs
+++ b/src/comp/util/common.rs
@@ -89,12 +89,10 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
     alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } }
 }
 
-fn is_main_name(path: [ast::ident]) -> bool {
-    str::eq(option::get(vec::last(path)), "main")
+fn is_main_name(path: middle::ast_map::path) -> bool {
+    option::get(vec::last(path)) == middle::ast_map::path_name("main")
 }
 
-
-
 //
 // Local Variables:
 // mode: rust
diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs
index 3d12fdaaa67..e95a256fe04 100644
--- a/src/rustdoc/attr_pass.rs
+++ b/src/rustdoc/attr_pass.rs
@@ -67,7 +67,7 @@ fn parse_item_attrs<T>(
     parse_attrs: fn~([ast::attribute]) -> T) -> T {
     astsrv::exec(srv) {|ctxt|
         let attrs = alt ctxt.ast_map.get(id) {
-          ast_map::node_item(item) { item.attrs }
+          ast_map::node_item(item, _) { item.attrs }
           _ {
             fail "parse_item_attrs: not an item";
           }
@@ -246,7 +246,7 @@ fn fold_enum(
                 alt ctxt.ast_map.get(doc.id) {
                   ast_map::node_item(@{
                     node: ast::item_enum(ast_variants, _), _
-                  }) {
+                  }, _) {
                     let ast_variant = option::get(
                         vec::find(ast_variants) {|v|
                             v.node.name == variant.name
@@ -351,14 +351,14 @@ fn merge_method_attrs(
         alt ctxt.ast_map.get(item_id) {
           ast_map::node_item(@{
             node: ast::item_iface(_, methods), _
-          }) {
+          }, _) {
             vec::map(methods) {|method|
                 (method.ident, attr_parser::parse_method(method.attrs))
             }
           }
           ast_map::node_item(@{
             node: ast::item_impl(_, _, _, methods), _
-          }) {
+          }, _) {
             vec::map(methods) {|method|
                 (method.ident, attr_parser::parse_method(method.attrs))
             }
diff --git a/src/rustdoc/prune_unexported_pass.rs b/src/rustdoc/prune_unexported_pass.rs
index 110b6952e96..41a035770b6 100644
--- a/src/rustdoc/prune_unexported_pass.rs
+++ b/src/rustdoc/prune_unexported_pass.rs
@@ -106,7 +106,7 @@ fn is_exported_from_mod(
 ) -> bool {
     astsrv::exec(srv) {|ctxt|
         alt ctxt.ast_map.get(mod_id) {
-          ast_map::node_item(item) {
+          ast_map::node_item(item, _) {
             alt item.node {
               ast::item_mod(m) {
                 ast_util::is_exported(item_name, m)
diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs
index a80905538b2..58cbff8edb2 100644
--- a/src/rustdoc/tystr_pass.rs
+++ b/src/rustdoc/tystr_pass.rs
@@ -49,7 +49,7 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
           ast_map::node_item(@{
             ident: ident,
             node: ast::item_fn(decl, _, blk), _
-          }) {
+          }, _) {
             some(pprust::fun_to_str(decl, ident, []))
           }
           _ {
@@ -86,7 +86,7 @@ fn get_ret_ty(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
         alt ctxt.ast_map.get(fn_id) {
           ast_map::node_item(@{
             node: ast::item_fn(decl, _, _), _
-          }) {
+          }, _) {
             ret_ty_to_str(decl)
           }
           _ { fail "get_ret_ty: undocumented invariant"; }
@@ -136,10 +136,10 @@ fn get_arg_tys(srv: astsrv::srv, fn_id: doc::ast_id) -> [(str, str)] {
         alt ctxt.ast_map.get(fn_id) {
           ast_map::node_item(@{
             node: ast::item_fn(decl, _, _), _
-          }) |
+          }, _) |
           ast_map::node_item(@{
             node: ast::item_res(decl, _, _, _, _), _
-          }) {
+          }, _) {
             decl_arg_tys(decl)
           }
           _ {
@@ -174,7 +174,7 @@ fn fold_const(
             alt ctxt.ast_map.get(doc.id) {
               ast_map::node_item(@{
                 node: ast::item_const(ty, _), _
-              }) {
+              }, _) {
                 pprust::ty_to_str(ty)
               }
               _ {
@@ -204,7 +204,7 @@ fn fold_enum(
                 alt ctxt.ast_map.get(doc.id) {
                   ast_map::node_item(@{
                     node: ast::item_enum(ast_variants, _), _
-                  }) {
+                  }, _) {
                     let ast_variant = option::get(
                         vec::find(ast_variants) {|v|
                             v.node.name == variant.name
@@ -243,7 +243,7 @@ fn fold_res(
             alt ctxt.ast_map.get(doc.id) {
               ast_map::node_item(@{
                 node: ast::item_res(decl, _, _, _, _), _
-              }) {
+              }, _) {
                 pprust::res_to_str(decl, doc.name, [])
               }
               _ { fail "fold_res: undocumented invariant"; }
@@ -324,7 +324,7 @@ fn get_method_ret_ty(
         alt ctxt.ast_map.get(item_id) {
           ast_map::node_item(@{
             node: ast::item_iface(_, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -336,7 +336,7 @@ fn get_method_ret_ty(
           }
           ast_map::node_item(@{
             node: ast::item_impl(_, _, _, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -360,7 +360,7 @@ fn get_method_sig(
         alt ctxt.ast_map.get(item_id) {
           ast_map::node_item(@{
             node: ast::item_iface(_, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -372,7 +372,7 @@ fn get_method_sig(
           }
           ast_map::node_item(@{
             node: ast::item_impl(_, _, _, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -412,7 +412,7 @@ fn get_method_arg_tys(
         alt ctxt.ast_map.get(item_id) {
           ast_map::node_item(@{
             node: ast::item_iface(_, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -424,7 +424,7 @@ fn get_method_arg_tys(
           }
           ast_map::node_item(@{
             node: ast::item_impl(_, _, _, methods), _
-          }) {
+          }, _) {
             alt vec::find(methods) {|method|
                 method.ident == method_name
             } {
@@ -476,7 +476,7 @@ fn fold_impl(
         alt ctxt.ast_map.get(doc.id) {
           ast_map::node_item(@{
             node: ast::item_impl(_, iface_ty, self_ty, _), _
-          }) {
+          }, _) {
             let iface_ty = option::map(iface_ty) {|iface_ty|
                 pprust::ty_to_str(iface_ty)
             };
@@ -551,7 +551,7 @@ fn fold_type(
               ast_map::node_item(@{
                 ident: ident,
                 node: ast::item_ty(ty, params), _
-              }) {
+              }, _) {
                 some(#fmt(
                     "type %s%s = %s",
                     ident,