diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 692e4e345df63..9e65e4ec18a97 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -60,6 +60,7 @@ pub struct EncodeParams<'self> { reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, + non_inlineable_statics: &'self HashSet, link_meta: &'self LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item<'self>, @@ -89,6 +90,7 @@ pub struct EncodeContext<'self> { reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, + non_inlineable_statics: &'self HashSet, link_meta: &'self LinkMeta, cstore: &'self cstore::CStore, encode_inlined_item: encode_inlined_item<'self>, @@ -907,7 +909,9 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(ecx, ebml_w, item.ident); let elt = ast_map::path_pretty_name(item.ident, item.id as u64); encode_path(ecx, ebml_w, path, elt); - (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); + if !ecx.non_inlineable_statics.contains(&item.id) { + (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); + } ebml_w.end_tag(); } item_fn(_, purity, _, ref generics, _) => { @@ -1728,6 +1732,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { encode_inlined_item, link_meta, reachable, + non_inlineable_statics, _ } = parms; let type_abbrevs = @mut HashMap::new(); @@ -1739,6 +1744,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { reexports2: reexports2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, + non_inlineable_statics: non_inlineable_statics, link_meta: link_meta, cstore: cstore, encode_inlined_item: encode_inlined_item, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 62fbdc41b0e70..d27bcde20649c 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -324,15 +324,16 @@ fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result { return single_result(datumblock.to_result(bcx)); } lit(ConstLit(lit_id)) => { - let llval = consts::get_const_val(bcx.ccx(), lit_id); + let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id); return single_result(rslt(bcx, llval)); } var(disr_val, repr) => { return adt::trans_case(bcx, repr, disr_val); } range(l1, l2) => { - return range_result(rslt(bcx, consts::const_expr(ccx, l1)), - rslt(bcx, consts::const_expr(ccx, l2))); + let (l1, _) = consts::const_expr(ccx, l1); + let (l2, _) = consts::const_expr(ccx, l2); + return range_result(rslt(bcx, l1), rslt(bcx, l2)); } vec_len(n, vec_len_eq, _) => { return single_result(rslt(bcx, C_int(ccx, n as int))); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f0238e8f5c550..823825b519ee1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2494,12 +2494,29 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { let sym = exported_name(ccx, my_path, ty, i.attrs); let v = match i.node { - ast::item_static(_, m, expr) => { + ast::item_static(_, _, expr) => { + // If this static came from an external crate, then + // we need to get the symbol from csearch instead of + // using the current crate's name/version + // information in the hash of the symbol + debug!("making %s", sym); + let sym = match ccx.external_srcs.find(&i.id) { + Some(&did) => { + debug!("but found in other crate..."); + csearch::get_symbol(ccx.sess.cstore, did) + } + None => sym + }; + // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. - let v = consts::const_expr(ccx, expr); + let (v, inlineable) = consts::const_expr(ccx, expr); ccx.const_values.insert(id, v); - exprt = (m == ast::MutMutable || i.vis == ast::public); + if !inlineable { + debug!("%s not inlined", sym); + ccx.non_inlineable_statics.insert(id); + } + exprt = true; unsafe { let llty = llvm::LLVMTypeOf(v); @@ -2950,6 +2967,7 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_ reexports2: cx.exp_map2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, + non_inlineable_statics: &cx.non_inlineable_statics, link_meta: link_meta, cstore: cx.sess.cstore, encode_inlined_item: ie, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 78d2228ff041c..a7a04627981a9 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -84,21 +84,21 @@ pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef { } pub fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr]) - -> (ValueRef, ValueRef, Type) { + -> (ValueRef, ValueRef, Type, bool) { unsafe { let vec_ty = ty::expr_ty(cx.tcx, e); let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty); let llunitty = type_of::type_of(cx, unit_ty); let unit_sz = machine::llsize_of(cx, llunitty); let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz); - let vs = es.map(|e| const_expr(cx, *e)); + let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e))); // If the vector contains enums, an LLVM array won't work. let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(vs) } else { C_array(llunitty, vs) }; - return (v, sz, llunitty); + return (v, sz, llunitty, inlineable.iter().fold(true, |a, &b| a && b)); } } @@ -157,7 +157,8 @@ fn const_deref(cx: &mut CrateContext, v: ValueRef, t: ty::t, explicit: bool) } } -pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::DefId) -> ValueRef { +pub fn get_const_val(cx: @mut CrateContext, + mut def_id: ast::DefId) -> (ValueRef, bool) { let contains_key = cx.const_values.contains_key(&def_id.node); if !ast_util::is_local(def_id) || !contains_key { if !ast_util::is_local(def_id) { @@ -172,11 +173,14 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::DefId) -> ValueRef _ => cx.tcx.sess.bug("expected a const to be an item") } } - cx.const_values.get_copy(&def_id.node) + (cx.const_values.get_copy(&def_id.node), + !cx.non_inlineable_statics.contains(&def_id.node)) } -pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { - let mut llconst = const_expr_unadjusted(cx, e); +pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> (ValueRef, bool) { + let (llconst, inlineable) = const_expr_unadjusted(cx, e); + let mut llconst = llconst; + let mut inlineable = inlineable; let ety = ty::expr_ty(cx.tcx, e); let adjustment = cx.tcx.adjustments.find_copy(&e.id); match adjustment { @@ -204,7 +208,10 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { // Don't copy data to do a deref+ref. let llptr = match maybe_ptr { Some(ptr) => ptr, - None => const_addr_of(cx, llconst) + None => { + inlineable = false; + const_addr_of(cx, llconst) + } }; match *autoref { ty::AutoUnsafe(m) | @@ -250,17 +257,27 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { e.repr(cx.tcx), ty_to_str(cx.tcx, ety), csize, tsize)); } - llconst + (llconst, inlineable) } -fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { +// the bool returned is whether this expression can be inlined into other crates +// if it's assigned to a static. +fn const_expr_unadjusted(cx: @mut CrateContext, + e: &ast::Expr) -> (ValueRef, bool) { + fn map_list(cx: @mut CrateContext, + exprs: &[@ast::Expr]) -> (~[ValueRef], bool) { + exprs.iter().map(|&e| const_expr(cx, e)) + .fold((~[], true), |(L, all_inlineable), (val, inlineable)| { + (vec::append_one(L, val), all_inlineable && inlineable) + }) + } unsafe { let _icx = push_ctxt("const_expr"); return match e.node { - ast::ExprLit(lit) => consts::const_lit(cx, e, *lit), + ast::ExprLit(lit) => (consts::const_lit(cx, e, *lit), true), ast::ExprBinary(_, b, e1, e2) => { - let te1 = const_expr(cx, e1); - let te2 = const_expr(cx, e2); + let (te1, _) = const_expr(cx, e1); + let (te2, _) = const_expr(cx, e2); let te2 = base::cast_shift_const_rhs(b, te1, te2); @@ -269,7 +286,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let ty = ty::expr_ty(cx.tcx, e1); let is_float = ty::type_is_fp(ty); let signed = ty::type_is_signed(ty); - return match b { + return (match b { ast::BiAdd => { if is_float { llvm::LLVMConstFAdd(te1, te2) } else { llvm::LLVMConstAdd(te1, te2) } @@ -338,13 +355,13 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { else { ConstICmp(IntUGT, te1, te2) } } }, - }; + }, true) }, ast::ExprUnary(_, u, e) => { - let te = const_expr(cx, e); + let (te, _) = const_expr(cx, e); let ty = ty::expr_ty(cx.tcx, e); let is_float = ty::type_is_fp(ty); - return match u { + return (match u { ast::UnBox(_) | ast::UnUniq | ast::UnDeref => { @@ -367,21 +384,21 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { if is_float { llvm::LLVMConstFNeg(te) } else { llvm::LLVMConstNeg(te) } } - } + }, true) } ast::ExprField(base, field, _) => { let bt = ty::expr_ty_adjusted(cx.tcx, base); let brepr = adt::represent_type(cx, bt); - let bv = const_expr(cx, base); + let (bv, inlineable) = const_expr(cx, base); do expr::with_field_tys(cx.tcx, bt, None) |discr, field_tys| { let ix = ty::field_idx_strict(cx.tcx, field.name, field_tys); - adt::const_get_field(cx, brepr, bv, discr, ix) + (adt::const_get_field(cx, brepr, bv, discr, ix), inlineable) } } ast::ExprIndex(_, base, index) => { let bt = ty::expr_ty_adjusted(cx.tcx, base); - let bv = const_expr(cx, base); + let (bv, inlineable) = const_expr(cx, base); let iv = match const_eval::eval_const_expr(cx.tcx, index) { const_eval::const_int(i) => i as u64, const_eval::const_uint(u) => u, @@ -422,15 +439,15 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { cx.sess.span_err(e.span, "const index-expr is out of bounds"); } - const_get_elt(cx, arr, [iv as c_uint]) + (const_get_elt(cx, arr, [iv as c_uint]), inlineable) } ast::ExprCast(base, _) => { let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); let basety = ty::expr_ty(cx.tcx, base); - let v = const_expr(cx, base); - match (expr::cast_type_kind(basety), - expr::cast_type_kind(ety)) { + let (v, inlineable) = const_expr(cx, base); + return (match (expr::cast_type_kind(basety), + expr::cast_type_kind(ety)) { (expr::cast_integral, expr::cast_integral) => { let s = ty::type_is_signed(basety) as Bool; @@ -476,17 +493,17 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { cx.sess.impossible_case(e.span, "bad combination of types for cast") } - } + }, inlineable) } ast::ExprAddrOf(ast::MutImmutable, sub) => { - let e = const_expr(cx, sub); - const_addr_of(cx, e) + let (e, _) = const_expr(cx, sub); + (const_addr_of(cx, e), false) } ast::ExprTup(ref es) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); - let vals = es.map(|&e| const_expr(cx, e)); - adt::trans_const(cx, repr, 0, vals) + let (vals, inlineable) = map_list(cx, *es); + (adt::trans_const(cx, repr, 0, vals), inlineable) } ast::ExprStruct(_, ref fs, ref base_opt) => { let ety = ty::expr_ty(cx.tcx, e); @@ -500,24 +517,29 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { do expr::with_field_tys(tcx, ety, Some(e.id)) |discr, field_tys| { - let cs: ~[ValueRef] = field_tys.iter().enumerate() + let cs = field_tys.iter().enumerate() .map(|(ix, &field_ty)| { match fs.iter().find(|f| field_ty.ident.name == f.ident.name) { Some(f) => const_expr(cx, (*f).expr), None => { match base_val { - Some(bv) => adt::const_get_field(cx, repr, bv, discr, ix), + Some((bv, inlineable)) => { + (adt::const_get_field(cx, repr, bv, discr, ix), + inlineable) + } None => cx.tcx.sess.span_bug(e.span, "missing struct field") } } } - }).collect(); - adt::trans_const(cx, repr, discr, cs) + }).to_owned_vec(); + let (cs, inlineable) = vec::unzip(cs.move_iter()); + (adt::trans_const(cx, repr, discr, cs), + inlineable.iter().fold(true, |a, &b| a && b)) } } ast::ExprVec(ref es, ast::MutImmutable) => { - let (v, _, _) = const_vec(cx, e, *es); - v + let (v, _, _, inlineable) = const_vec(cx, e, *es); + (v, inlineable) } ast::ExprVstore(sub, ast::ExprVstoreSlice) => { match sub.node { @@ -528,7 +550,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { } } ast::ExprVec(ref es, ast::MutImmutable) => { - let (cv, sz, llunitty) = const_vec(cx, e, *es); + let (cv, sz, llunitty, _) = const_vec(cx, e, *es); let llty = val_ty(cv); let gv = do "const".with_c_str |name| { llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name) @@ -537,7 +559,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { llvm::LLVMSetGlobalConstant(gv, True); SetLinkage(gv, PrivateLinkage); let p = const_ptrcast(cx, gv, llunitty); - C_struct([p, sz]) + (C_struct([p, sz]), false) } _ => cx.sess.span_bug(e.span, "bad const-slice expr") } @@ -551,13 +573,13 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { const_eval::const_uint(i) => i as uint, _ => cx.sess.span_bug(count.span, "count must be integral const expression.") }; - let vs = vec::from_elem(n, const_expr(cx, elem)); + let vs = vec::from_elem(n, const_expr(cx, elem).first()); let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(vs) } else { C_array(llunitty, vs) }; - v + (v, true) } ast::ExprPath(ref pth) => { // Assert that there are no type parameters in this path. @@ -568,10 +590,10 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { Some(&ast::DefFn(def_id, _purity)) => { if !ast_util::is_local(def_id) { let ty = csearch::get_type(cx.tcx, def_id).ty; - base::trans_external_path(cx, def_id, ty) + (base::trans_external_path(cx, def_id, ty), true) } else { assert!(ast_util::is_local(def_id)); - base::get_item_val(cx, def_id.node) + (base::get_item_val(cx, def_id.node), true) } } Some(&ast::DefStatic(def_id, false)) => { @@ -583,12 +605,12 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let vinfo = ty::enum_variant_with_id(cx.tcx, enum_did, variant_did); - adt::trans_const(cx, repr, vinfo.disr_val, []) + (adt::trans_const(cx, repr, vinfo.disr_val, []), true) } Some(&ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); - C_null(llty) + (C_null(llty), true) } _ => { cx.sess.span_bug(e.span, "expected a const, fn, struct, or variant def") @@ -601,8 +623,8 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { Some(&ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); - let arg_vals = args.map(|a| const_expr(cx, *a)); - adt::trans_const(cx, repr, 0, arg_vals) + let (arg_vals, inlineable) = map_list(cx, *args); + (adt::trans_const(cx, repr, 0, arg_vals), inlineable) } Some(&ast::DefVariant(enum_did, variant_did, _)) => { let ety = ty::expr_ty(cx.tcx, e); @@ -610,13 +632,14 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let vinfo = ty::enum_variant_with_id(cx.tcx, enum_did, variant_did); - let arg_vals = args.map(|a| const_expr(cx, *a)); - adt::trans_const(cx, repr, vinfo.disr_val, arg_vals) + let (arg_vals, inlineable) = map_list(cx, *args); + (adt::trans_const(cx, repr, vinfo.disr_val, arg_vals), + inlineable) } _ => cx.sess.span_bug(e.span, "expected a struct or variant def") } } - ast::ExprParen(e) => { return const_expr(cx, e); } + ast::ExprParen(e) => { const_expr(cx, e) } _ => cx.sess.span_bug(e.span, "bad constant expression type in consts::const_expr") }; diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 6eb2fcf25fd3c..9ee7f09253b54 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -61,6 +61,13 @@ pub struct CrateContext { finished_tydescs: bool, // Track mapping of external ids to local items imported for inlining external: HashMap>, + // Backwards version of the `external` map (inlined items to where they + // came from) + external_srcs: HashMap, + // A set of static items which cannot be inlined into other crates. This + // will pevent in ii_item() structures from being encoded into the metadata + // that is generated + non_inlineable_statics: HashSet, // Cache instances of monomorphized functions monomorphized: HashMap, monomorphizing: HashMap, @@ -189,6 +196,8 @@ impl CrateContext { tydescs: HashMap::new(), finished_tydescs: false, external: HashMap::new(), + external_srcs: HashMap::new(), + non_inlineable_statics: HashSet::new(), monomorphized: HashMap::new(), monomorphizing: HashMap::new(), type_use_cache: HashMap::new(), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index b351fe91e6f1c..0a55786975832 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -116,7 +116,7 @@ return type, such as `while` loops or assignments (`a = b`). use back::abi; use back::link; -use lib::llvm::{ValueRef, llvm, SetLinkage, ExternalLinkage, False}; +use lib::llvm::{ValueRef, llvm, SetLinkage, False}; use lib; use metadata::csearch; use middle::trans::_match; @@ -135,6 +135,7 @@ use middle::trans::datum::*; use middle::trans::debuginfo; use middle::trans::machine; use middle::trans::meth; +use middle::trans::inline; use middle::trans::tvec; use middle::trans::type_of; use middle::ty::struct_fields; @@ -987,6 +988,15 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { ast::DefStatic(did, _) => { let const_ty = expr_ty(bcx, ref_expr); + fn get_did(ccx: @mut CrateContext, did: ast::DefId) + -> ast::DefId { + if did.crate != ast::LOCAL_CRATE { + inline::maybe_instantiate_inline(ccx, did) + } else { + did + } + } + fn get_val(bcx: @mut Block, did: ast::DefId, const_ty: ty::t) -> ValueRef { // For external constants, we don't inline. @@ -1018,7 +1028,6 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { llty.to_ref(), buf) }; - SetLinkage(llval, ExternalLinkage); let extern_const_values = &mut bcx.ccx().extern_const_values; extern_const_values.insert(did, llval); llval @@ -1026,6 +1035,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { } } + let did = get_did(bcx.ccx(), did); let val = get_val(bcx, did, const_ty); DatumBlock { bcx: bcx, diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index cfc9c8a2e17cf..a571e56a48ec0 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use lib::llvm::{AvailableExternallyLinkage, SetLinkage}; use metadata::csearch; use middle::astencode; use middle::trans::base::{push_ctxt, impl_self, no_self}; @@ -53,16 +53,36 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) } csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); + ccx.external_srcs.insert(item.id, fn_id); ccx.stats.n_inlines += 1; trans_item(ccx, item); + + // We're bringing an external global into this crate, but we don't + // want to create two copies of the global. If we do this, then if + // you take the address of the global in two separate crates you get + // two different addresses. This is bad for things like conditions, + // but it could possibly have other adverse side effects. We still + // want to achieve the optimizations related to this global, + // however, so we use the available_externally linkage which llvm + // provides + match item.node { + ast::item_static(*) => { + let g = get_item_val(ccx, item.id); + SetLinkage(g, AvailableExternallyLinkage); + } + _ => {} + } + local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); + ccx.external_srcs.insert(item.id, fn_id); local_def(item.id) } csearch::found_parent(parent_id, ast::ii_item(item)) => { ccx.external.insert(parent_id, Some(item.id)); + ccx.external_srcs.insert(item.id, parent_id); let mut my_id = 0; match item.node { ast::item_enum(_, _) => { @@ -86,6 +106,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) csearch::found(ast::ii_method(impl_did, is_provided, mth)) => { ccx.stats.n_inlines += 1; ccx.external.insert(fn_id, Some(mth.id)); + ccx.external_srcs.insert(mth.id, fn_id); // If this is a default method, we can't look up the // impl type. But we aren't going to translate anyways, so don't. if is_provided { return local_def(mth.id); } diff --git a/src/test/auxiliary/xcrate_static_addresses.rs b/src/test/auxiliary/xcrate_static_addresses.rs index 3a05462d856da..f0df2b1e71ede 100644 --- a/src/test/auxiliary/xcrate_static_addresses.rs +++ b/src/test/auxiliary/xcrate_static_addresses.rs @@ -10,12 +10,21 @@ pub static global: int = 3; +static global0: int = 4; +pub static global2: &'static int = &global0; + pub fn verify_same(a: &'static int) { let a = a as *int as uint; let b = &global as *int as uint; assert_eq!(a, b); } +pub fn verify_same2(a: &'static int) { + let a = a as *int as uint; + let b = global2 as *int as uint; + assert_eq!(a, b); +} + condition!{ pub test: int -> (); } pub fn raise() { diff --git a/src/test/run-pass/xcrate-static-addresses.rs b/src/test/run-pass/xcrate-static-addresses.rs index 059a6f75ac82e..7eb4adfd06757 100644 --- a/src/test/run-pass/xcrate-static-addresses.rs +++ b/src/test/run-pass/xcrate-static-addresses.rs @@ -17,6 +17,7 @@ use other = xcrate_static_addresses; pub fn main() { other::verify_same(&other::global); + other::verify_same2(other::global2); // Previously this fail'd because there were two addresses that were being // used when declaring constants.