diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 223a5eef614c1..6d83ab152d5bc 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() { ... }`). - 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 fda57c9dc610a..3242dafbd1cc1 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 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 87216b1add0fa..0b014c9e6a20c 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 6f71def11886d..acbd09f671ba1 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 027f2dbc717b5..31c9b60f478a2 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 eb4acec25510a..e046b5cb11193 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 a72bac3e3b2cd..6259f8fe1cc2e 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 8ebda9a6678df..0afaf88aaad91 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 51db0adf5b775..3818739c6cce8 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>, available_drop_glues: RefCell, String>>, use_dll_storage_attrs: bool, } @@ -100,6 +99,7 @@ pub struct LocalCrateContext<'tcx> { /// Cache instances of monomorphized functions monomorphized: RefCell, ValueRef>>, monomorphizing: RefCell>, + available_monomorphizations: RefCell>, /// Cache generated vtables vtables: RefCell, 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> { - &self.shared.available_monomorphizations + &self.local.available_monomorphizations } pub fn available_drop_glues(&self) -> &RefCell, String>> { diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index ab8cfa0ce3b7e..d203aeca0a757 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 63158cdee9247..c5524ab8f38f9 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], dest: Option) -> 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 9a53c3f0bcdf5..f860fe44f28e7 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 { - 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 7039968b029ac..feb2b87918327 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 d086aa93a6f6b..3d74cf46e6ec3 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);