about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/tydecode.rs14
-rw-r--r--src/librustc/middle/astencode.rs48
-rw-r--r--src/librustc/middle/ty.rs5
-rw-r--r--src/librustc/util/ppaux.rs24
-rw-r--r--src/librustc_trans/trans/callee.rs8
-rw-r--r--src/librustc_trans/trans/closure.rs16
-rw-r--r--src/librustc_trans/trans/common.rs3
-rw-r--r--src/librustc_trans/trans/consts.rs7
-rw-r--r--src/librustc_trans/trans/context.rs6
-rw-r--r--src/librustc_trans/trans/controlflow.rs10
-rw-r--r--src/librustc_trans/trans/expr.rs3
-rw-r--r--src/librustc_trans/trans/inline.rs20
-rw-r--r--src/librustc_trans/trans/meth.rs7
-rw-r--r--src/librustc_trans/trans/monomorphize.rs4
14 files changed, 86 insertions, 89 deletions
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 223a5eef614..6d83ab152d5 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -50,9 +50,6 @@ pub enum DefIdSource {
     // Identifies a type alias (`type X = ...`).
     TypeWithId,
 
-    // Identifies a type parameter (`fn foo<X>() { ... }`).
-    TypeParameter,
-
     // Identifies a region parameter (`fn foo<'X>() { ... }`).
     RegionParameter,
 
@@ -193,7 +190,7 @@ pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: us
                                   tcx: &ty::ctxt<'tcx>, conv: F) -> subst::Substs<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    debug!("parse_substs_data {}", data_log_string(data, pos));
+    debug!("parse_substs_data{}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_substs(&mut st, conv)
 }
@@ -542,7 +539,14 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
                                          len: len };
 
         match tcx.rcache.borrow().get(&key).cloned() {
-          Some(tt) => return tt,
+          Some(tt) => {
+            // If there is a closure buried in the type some where, then we
+            // need to re-convert any def ids (see case 'k', below). That means
+            // we can't reuse the cached version.
+            if !ty::type_has_ty_closure(tt) {
+                return tt;
+            }
+          }
           None => {}
         }
         let mut ps = PState {
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index fda57c9dc61..3242dafbd1c 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -20,7 +20,7 @@ use middle::def;
 use metadata::encoder as e;
 use middle::region;
 use metadata::tydecode;
-use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
+use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
 use metadata::tydecode::{RegionParameter, ClosureSource};
 use metadata::tyencode;
 use middle::cast;
@@ -346,13 +346,6 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
 // ______________________________________________________________________
 // Encoding and decoding the AST itself
 //
-// The hard work is done by an autogenerated module astencode_gen.  To
-// regenerate astencode_gen, run src/etc/gen-astencode.  It will
-// replace astencode_gen with a dummy file and regenerate its
-// contents.  If you get compile errors, the dummy file
-// remains---resolve the errors and then rerun astencode_gen.
-// Annoying, I know, but hopefully only temporary.
-//
 // When decoding, we have to renumber the AST so that the node ids that
 // appear within are disjoint from the node ids in our existing ASTs.
 // We also have to adjust the spans: for now we just insert a dummy span,
@@ -656,35 +649,6 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
     }
 }
 
-impl<'tcx> tr for MethodOrigin<'tcx> {
-    fn tr(&self, dcx: &DecodeContext) -> MethodOrigin<'tcx> {
-        match *self {
-            ty::MethodStatic(did) => ty::MethodStatic(did.tr(dcx)),
-            ty::MethodStaticClosure(did) => {
-                ty::MethodStaticClosure(did.tr(dcx))
-            }
-            ty::MethodTypeParam(ref mp) => {
-                ty::MethodTypeParam(
-                    ty::MethodParam {
-                        // def-id is already translated when we read it out
-                        trait_ref: mp.trait_ref.clone(),
-                        method_num: mp.method_num,
-                        impl_def_id: mp.impl_def_id.tr(dcx),
-                    }
-                )
-            }
-            ty::MethodTraitObject(ref mo) => {
-                ty::MethodTraitObject(
-                    ty::MethodObject {
-                        trait_ref: mo.trait_ref.clone(),
-                        .. *mo
-                    }
-                )
-            }
-        }
-    }
-}
-
 pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
     kind.encode(ebml_w).unwrap();
 }
@@ -1473,10 +1437,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                            -> subst::Substs<'tcx> {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_substs_data(doc.data,
-                                        dcx.cdata.cnum,
-                                        doc.start,
-                                        dcx.tcx,
-                                        |s, a| this.convert_def_id(dcx, s, a)))
+                                           dcx.cdata.cnum,
+                                           doc.start,
+                                           dcx.tcx,
+                                           |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap()
     }
 
@@ -1617,7 +1581,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                       -> ast::DefId {
         let r = match source {
             NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
-            TypeParameter | ClosureSource => dcx.tr_intern_def_id(did)
+            ClosureSource => dcx.tr_intern_def_id(did)
         };
         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
         return r;
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 87216b1add0..0b014c9e6a2 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -814,6 +814,7 @@ bitflags! {
         const HAS_REGIONS       = 1 << 5,
         const HAS_TY_ERR        = 1 << 6,
         const HAS_PROJECTION    = 1 << 7,
+        const HAS_TY_CLOSURE    = 1 << 8,
         const NEEDS_SUBST       = TypeFlags::HAS_PARAMS.bits |
                                   TypeFlags::HAS_SELF.bits |
                                   TypeFlags::HAS_REGIONS.bits,
@@ -985,6 +986,9 @@ pub fn type_needs_infer(ty: Ty) -> bool {
 pub fn type_has_projection(ty: Ty) -> bool {
     ty.flags.get().intersects(TypeFlags::HAS_PROJECTION)
 }
+pub fn type_has_ty_closure(ty: Ty) -> bool {
+    ty.flags.get().intersects(TypeFlags::HAS_TY_CLOSURE)
+}
 
 pub fn type_has_late_bound_regions(ty: Ty) -> bool {
     ty.flags.get().intersects(TypeFlags::HAS_RE_LATE_BOUND)
@@ -2960,6 +2964,7 @@ impl FlagComputation {
             }
 
             &ty_closure(_, substs) => {
+                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_substs(substs);
             }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 6f71def1188..acbd09f671b 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -304,11 +304,18 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
         s
     }
 
-    fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
+    fn closure_to_string<'tcx>(cx: &ctxt<'tcx>,
+                               cty: &ty::ClosureTy<'tcx>,
+                               did: &ast::DefId)
+                               -> String {
         let mut s = String::new();
         s.push_str("[closure");
         push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
-        s.push(']');
+        if cx.sess.verbose() {
+            s.push_str(&format!(" id={:?}]", did));
+        } else {
+            s.push(']');
+        }
         s
     }
 
@@ -407,13 +414,20 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
         ty_closure(ref did, substs) => {
             let closure_tys = cx.closure_tys.borrow();
             closure_tys.get(did).map(|closure_type| {
-                closure_to_string(cx, &closure_type.subst(cx, substs))
+                closure_to_string(cx, &closure_type.subst(cx, substs), did)
             }).unwrap_or_else(|| {
+                let id_str = if cx.sess.verbose() {
+                    format!(" id={:?}", did)
+                } else {
+                    "".to_owned()
+                };
+
+
                 if did.krate == ast::LOCAL_CRATE {
                     let span = cx.map.span(did.node);
-                    format!("[closure {}]", span.repr(cx))
+                    format!("[closure {}{}]", span.repr(cx), id_str)
                 } else {
-                    format!("[closure]")
+                    format!("[closure{}]", id_str)
                 }
             })
         }
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 027f2dbc717..31c9b60f478 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -117,9 +117,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
             _ => {
                 bcx.tcx().sess.span_bug(
                     expr.span,
-                    &format!("type of callee is neither bare-fn nor closure: \
-                             {}",
-                            bcx.ty_to_string(datum.ty)));
+                    &format!("type of callee is neither bare-fn nor closure: {}",
+                             bcx.ty_to_string(datum.ty)));
             }
         }
     }
@@ -506,6 +505,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
         false
     };
 
+    debug!("trans_fn_ref_with_substs({}) must_monomorphise: {}",
+           def_id.repr(tcx), must_monomorphise);
+
     // Create a monomorphic version of generic functions
     if must_monomorphise {
         // Should be either intra-crate or inlined.
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index eb4acec2551..e046b5cb111 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -153,7 +153,8 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
 
     match ccx.closure_vals().borrow().get(&mono_id) {
         Some(&llfn) => {
-            debug!("get_or_create_declaration_if_closure(): found closure");
+            debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
+                   mono_id, ccx.tn().val_to_string(llfn));
             return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
         }
         None => {}
@@ -173,9 +174,10 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
     attributes::inline(llfn, attributes::InlineAttr::Hint);
 
     debug!("get_or_create_declaration_if_closure(): inserting new \
-            closure {:?} (type {})",
+            closure {:?} (type {}): {:?}",
            mono_id,
-           ccx.tn().type_to_string(val_ty(llfn)));
+           ccx.tn().type_to_string(val_ty(llfn)),
+           ccx.tn().val_to_string(llfn));
     ccx.closure_vals().borrow_mut().insert(mono_id, llfn);
 
     Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
@@ -198,9 +200,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
         Dest::Ignore(ccx) => ccx
     };
     let tcx = ccx.tcx();
-    let _icx = push_ctxt("closure::trans_closure");
+    let _icx = push_ctxt("closure::trans_closure_expr");
 
-    debug!("trans_closure()");
+    debug!("trans_closure_expr()");
 
     let closure_id = ast_util::local_def(id);
     let llfn = get_or_create_declaration_if_closure(
@@ -230,7 +232,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
                   &[],
                   sig.output,
                   function_type.abi,
-                  ClosureEnv::Closure(&freevars[..]));
+                  ClosureEnv::Closure(&freevars));
 
     // Don't hoist this to the top of the function. It's perfectly legitimate
     // to have a zero-size closure (in which case dest will be `Ignore`) and
@@ -238,7 +240,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     let (mut bcx, dest_addr) = match dest {
         Dest::SaveIn(bcx, p) => (bcx, p),
         Dest::Ignore(_) => {
-            debug!("trans_closure() ignoring result");
+            debug!("trans_closure_expr() ignoring result");
             return None;
         }
     };
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index a72bac3e3b2..6259f8fe1cc 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -1000,7 +1000,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         None => { }
     }
 
-    debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
+    debug!("trans fulfill_obligation: trait_ref={} def_id={:?}",
+           trait_ref.repr(ccx.tcx()), trait_ref.def_id());
 
     ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
     let infcx = infer::new_infer_ctxt(tcx);
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 8ebda9a6678..0afaf88aaad 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -221,6 +221,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           qualif: check_const::ConstQualif,
                                           param_substs: &'tcx Substs<'tcx>)
                                           -> ValueRef {
+    debug!("get_const_expr_as_global: {:?}", expr.id);
     // Special-case constants to cache a common global for all uses.
     match expr.node {
         ast::ExprPath(..) => {
@@ -228,6 +229,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             match def {
                 def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
+                        debug!("get_const_expr_as_global ({:?}): found const {:?}",
+                               expr.id, def_id);
                         return get_const_val(ccx, def_id, expr);
                     }
                 }
@@ -911,7 +914,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           }
           ast::ExprClosure(_, ref decl, ref body) => {
             closure::trans_closure_expr(closure::Dest::Ignore(cx),
-                                        &**decl, &**body, e.id,
+                                        decl,
+                                        body,
+                                        e.id,
                                         param_substs);
             C_null(type_of::type_of(cx, ety))
           }
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 51db0adf5b7..3818739c6cc 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -73,7 +73,6 @@ pub struct SharedCrateContext<'tcx> {
     check_overflow: bool,
     check_drop_flag_for_sanity: bool,
 
-    available_monomorphizations: RefCell<FnvHashSet<String>>,
     available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
     use_dll_storage_attrs: bool,
 }
@@ -100,6 +99,7 @@ pub struct LocalCrateContext<'tcx> {
     /// Cache instances of monomorphized functions
     monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
     monomorphizing: RefCell<DefIdMap<usize>>,
+    available_monomorphizations: RefCell<FnvHashSet<String>>,
     /// Cache generated vtables
     vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
     /// Cache of constant strings,
@@ -321,7 +321,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
             },
             check_overflow: check_overflow,
             check_drop_flag_for_sanity: check_drop_flag_for_sanity,
-            available_monomorphizations: RefCell::new(FnvHashSet()),
             available_drop_glues: RefCell::new(FnvHashMap()),
             use_dll_storage_attrs: use_dll_storage_attrs,
         };
@@ -452,6 +451,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
                 external_srcs: RefCell::new(NodeMap()),
                 monomorphized: RefCell::new(FnvHashMap()),
                 monomorphizing: RefCell::new(DefIdMap()),
+                available_monomorphizations: RefCell::new(FnvHashSet()),
                 vtables: RefCell::new(FnvHashMap()),
                 const_cstr_cache: RefCell::new(FnvHashMap()),
                 const_unsized: RefCell::new(FnvHashMap()),
@@ -709,7 +709,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
     }
 
     pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
-        &self.shared.available_monomorphizations
+        &self.local.available_monomorphizations
     }
 
     pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs
index ab8cfa0ce3b..d203aeca0a7 100644
--- a/src/librustc_trans/trans/controlflow.rs
+++ b/src/librustc_trans/trans/controlflow.rs
@@ -30,7 +30,6 @@ use syntax::ast;
 use syntax::ast_util;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
-use syntax::visit::Visitor;
 
 pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                               s: &ast::Stmt)
@@ -171,16 +170,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // if true { .. } [else { .. }]
             bcx = trans_block(bcx, &*thn, dest);
             trans::debuginfo::clear_source_location(bcx.fcx);
-
-            if let Some(elexpr) = els {
-                let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx };
-                trans.visit_expr(&*elexpr);
-            }
         } else {
-            // if false { .. } [else { .. }]
-            let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx };
-            trans.visit_block(&*thn);
-
             if let Some(elexpr) = els {
                 bcx = expr::trans_into(bcx, &*elexpr, dest);
                 trans::debuginfo::clear_source_location(bcx.fcx);
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 63158cdee92..c5524ab8f38 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -1145,7 +1145,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
             };
-            closure::trans_closure_expr(dest, &**decl, &**body, expr.id, bcx.fcx.param_substs)
+            closure::trans_closure_expr(dest, decl, body, expr.id, bcx.fcx.param_substs)
                 .unwrap_or(bcx)
         }
         ast::ExprCall(ref f, ref args) => {
@@ -1956,6 +1956,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                          args: &'a [P<ast::Expr>],
                                          dest: Option<Dest>)
                                          -> Block<'blk, 'tcx> {
+    debug!("trans_overloaded_call {}", expr.id);
     let method_call = MethodCall::expr(expr.id);
     let method_type = bcx.tcx()
                          .method_map
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index 9a53c3f0bcd..f860fe44f28 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -21,11 +21,13 @@ use syntax::ast_util::local_def;
 
 fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
     -> Option<ast::DefId> {
-    let _icx = push_ctxt("maybe_instantiate_inline");
+    debug!("instantiate_inline({:?})", fn_id);
+    let _icx = push_ctxt("instantiate_inline");
+
     match ccx.external().borrow().get(&fn_id) {
         Some(&Some(node_id)) => {
             // Already inline
-            debug!("maybe_instantiate_inline({}): already inline as node id {}",
+            debug!("instantiate_inline({}): already inline as node id {}",
                    ty::item_path_str(ccx.tcx(), fn_id), node_id);
             return Some(local_def(node_id));
         }
@@ -52,7 +54,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
 
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-            trans_item(ccx, &**item);
+            trans_item(ccx, item);
 
             let linkage = match item.node {
                 ast::ItemFn(_, _, _, _, ref generics, _) => {
@@ -118,7 +120,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
                 }
               }
             }
-            _ => ccx.sess().bug("maybe_instantiate_inline: item has a \
+            _ => ccx.sess().bug("instantiate_inline: item has a \
                                  non-enum, non-struct parent")
           }
           trans_item(ccx, &**item);
@@ -126,7 +128,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
         }
         csearch::FoundAst::FoundParent(_, _) => {
             ccx.sess().bug("maybe_get_item_ast returned a FoundParent \
-             with a non-item parent");
+                            with a non-item parent");
         }
         csearch::FoundAst::Found(&ast::IITraitItem(_, ref trait_item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
@@ -167,8 +169,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
                              empty_substs,
                              impl_item.id,
                              &[]);
-                    // Use InternalLinkage so LLVM can optimize more aggressively.
-                    SetLinkage(llfn, InternalLinkage);
+                    // See linkage comments on items.
+                    if ccx.sess().opts.cg.codegen_units == 1 {
+                        SetLinkage(llfn, InternalLinkage);
+                    } else {
+                        SetLinkage(llfn, AvailableExternallyLinkage);
+                    }
                 }
             }
 
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 7039968b029..feb2b879183 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -118,6 +118,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match origin {
         ty::MethodStatic(did) |
         ty::MethodStaticClosure(did) => {
+            debug!("trans_method_callee: static, {:?}", did);
             Callee {
                 bcx: bcx,
                 data: Fn(callee::trans_fn_ref(bcx.ccx(),
@@ -134,9 +135,11 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }) => {
             let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
             let span = bcx.tcx().map.span(method_call.expr_id);
-            debug!("method_call={:?} trait_ref={}",
+            debug!("method_call={:?} trait_ref={} trait_ref id={:?} substs={:?}",
                    method_call,
-                   trait_ref.repr(bcx.tcx()));
+                   trait_ref.repr(bcx.tcx()),
+                   trait_ref.0.def_id,
+                   trait_ref.0.substs);
             let origin = fulfill_obligation(bcx.ccx(),
                                             span,
                                             trait_ref.clone());
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index d086aa93a6f..3d74cf46e6e 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -60,6 +60,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     };
 
     let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
+
+    debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
     let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
 
     match ccx.monomorphized().borrow().get(&hash_id) {
@@ -97,8 +99,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     }
 
-    debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
-
     debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
 
     let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);