Skip to content
Closed
19 changes: 7 additions & 12 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
if len > 0u || should_inline {
(ecx.encode_inlined_item)(
ecx, ebml_w, impl_path,
ii_method(local_def(parent_id), m));
ii_method(local_def(parent_id), false, m));
} else {
encode_symbol(ecx, ebml_w, m.id);
}
Expand Down Expand Up @@ -1123,21 +1123,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
}

provided(m) => {
// This is obviously a bogus assert but I don't think this
// ever worked before anyhow...near as I can tell, before
// we would emit two items.
if method_ty.explicit_self == sty_static {
tcx.sess.span_unimpl(
item.span,
fmt!("Method %s is both provided and static",
token::ident_to_str(&method_ty.ident)));
// If this is a static method, we've already encoded
// this.
if method_ty.explicit_self != sty_static {
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
}
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
encode_method_sort(ebml_w, 'p');
(ecx.encode_inlined_item)(
ecx, ebml_w, path,
ii_method(local_def(item.id), m));
ii_method(local_def(item.id), true, m));
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
match *ii {
//hack: we're not dropping items
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
ast::ii_method(d, m) => ast::ii_method(d, fld.fold_method(m)),
ast::ii_method(d, is_provided, m) =>
ast::ii_method(d, is_provided, fld.fold_method(m)),
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
}
}
Expand All @@ -340,7 +341,8 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)

match ii {
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
ast::ii_method(d, m) => ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m)),
ast::ii_method(d, is_provided, m) =>
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
LintSpec {
lint: default_methods,
desc: "allow default methods",
default: deny
default: allow
}),

("unused_unsafe",
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ impl cmt_ {
}
}

impl Repr for cmt {
impl Repr for cmt_ {
fn repr(&self, tcx: ty::ctxt) -> ~str {
fmt!("{%s id:%d m:%? ty:%s}",
self.cat.repr(tcx),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
let _icx = push_ctxt("trans_res_dtor");
if !substs.is_empty() {
let did = if did.crate != ast::local_crate {
inline::maybe_instantiate_inline(ccx, did, true)
inline::maybe_instantiate_inline(ccx, did)
} else {
did
};
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ pub fn trans_fn_ref_with_vtables(
def_id: ast::def_id, // def id of fn
ref_id: ast::node_id, // node id of use of fn; may be zero if N/A
type_params: &[ty::t], // values for fn's ty params
vtables: Option<typeck::vtable_res>)
vtables: Option<typeck::vtable_res>) // vtables for the call
-> FnData {
//!
//
Expand Down Expand Up @@ -361,8 +361,7 @@ pub fn trans_fn_ref_with_vtables(
// def_id to the local id of the inlined copy.
let def_id = {
if def_id.crate != ast::local_crate {
let may_translate = opt_impl_did.is_none();
inline::maybe_instantiate_inline(ccx, def_id, may_translate)
inline::maybe_instantiate_inline(ccx, def_id)
} else {
def_id
}
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,6 @@ impl Repr for param_substs {
}
}

impl Repr for @param_substs {
fn repr(&self, tcx: ty::ctxt) -> ~str {
param_substs_to_str(*self, tcx)
}
}

// Function context. Every LLVM function we create will have one of
// these.
pub struct fn_ctxt_ {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::def_id) -> ValueRef
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) {
def_id = inline::maybe_instantiate_inline(cx, def_id, true);
def_id = inline::maybe_instantiate_inline(cx, def_id);
}
match cx.tcx.items.get_copy(&def_id.node) {
ast_map::node_item(@ast::item {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
fn get_did(ccx: @mut CrateContext, did: ast::def_id)
-> ast::def_id {
if did.crate != ast::local_crate {
inline::maybe_instantiate_inline(ccx, did, true)
inline::maybe_instantiate_inline(ccx, did)
} else {
did
}
Expand Down
14 changes: 5 additions & 9 deletions src/librustc/middle/trans/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ use syntax::ast;
use syntax::ast_map::path_name;
use syntax::ast_util::local_def;

// `translate` will be true if this function is allowed to translate the
// item and false otherwise. Currently, this parameter is set to false when
// translating default methods.
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
translate: bool)
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id)
-> ast::def_id {
let _icx = push_ctxt("maybe_instantiate_inline");
match ccx.external.find(&fn_id) {
Expand Down Expand Up @@ -59,7 +55,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
csearch::found(ast::ii_item(item)) => {
ccx.external.insert(fn_id, Some(item.id));
ccx.stats.n_inlines += 1;
if translate { trans_item(ccx, item); }
trans_item(ccx, item);
local_def(item.id)
}
csearch::found(ast::ii_foreign(item)) => {
Expand All @@ -81,19 +77,19 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
_ => ccx.sess.bug("maybe_instantiate_inline: item has a \
non-enum parent")
}
if translate { trans_item(ccx, item); }
trans_item(ccx, item);
local_def(my_id)
}
csearch::found_parent(_, _) => {
ccx.sess.bug("maybe_get_item_ast returned a found_parent \
with a non-item parent");
}
csearch::found(ast::ii_method(impl_did, mth)) => {
csearch::found(ast::ii_method(impl_did, is_provided, mth)) => {
ccx.stats.n_inlines += 1;
ccx.external.insert(fn_id, Some(mth.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 !translate { return local_def(mth.id); }
if is_provided { return local_def(mth.id); }

let impl_tpt = ty::lookup_item_type(ccx.tcx, impl_did);
let num_type_params =
Expand Down
60 changes: 50 additions & 10 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,26 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
let _icx = push_ctxt("monomorphic_fn");
let mut must_cast = false;
let substs = real_substs.tps.iter().transform(|t| {

let do_normalize = |t: &ty::t| {
match normalize_for_monomorphization(ccx.tcx, *t) {
Some(t) => { must_cast = true; t }
None => *t
}
}).collect::<~[ty::t]>();

for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
for substs.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
};

let psubsts = @param_substs {
tys: substs,
tys: real_substs.tps.map(|x| do_normalize(x)),
vtables: vtables,
self_ty: real_substs.self_ty,
self_ty: real_substs.self_ty.map(|x| do_normalize(x)),
self_vtable: self_vtable
};

for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
for psubsts.tys.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len());


let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
&*psubsts,
Some(param_uses));
Expand Down Expand Up @@ -109,6 +111,10 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
let llitem_ty = tpt.ty;

// We need to do special handling of the substitutions if we are
// calling a static provided method. This is sort of unfortunate.
let mut is_static_provided = None;

let map_node = session::expect(
ccx.sess,
ccx.tcx.items.find_copy(&fn_id.node),
Expand All @@ -127,6 +133,12 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
return (get_item_val(ccx, fn_id.node), true);
}
ast_map::node_trait_method(@ast::provided(m), _, pt) => {
// If this is a static provided method, indicate that
// and stash the number of params on the method.
if m.explicit_self.node == ast::sty_static {
is_static_provided = Some(m.generics.ty_params.len());
}

(pt, m.ident, m.span)
}
ast_map::node_trait_method(@ast::required(_), _, _) => {
Expand All @@ -151,8 +163,36 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
};

let mono_ty = ty::subst_tps(ccx.tcx, psubsts.tys,
psubsts.self_ty, llitem_ty);
debug!("monomorphic_fn about to subst into %s", llitem_ty.repr(ccx.tcx));
let mono_ty = match is_static_provided {
None => ty::subst_tps(ccx.tcx, psubsts.tys,
psubsts.self_ty, llitem_ty),
Some(num_method_ty_params) => {
// Static default methods are a little unfortunate, in
// that the "internal" and "external" type of them differ.
// Internally, the method body can refer to Self, but the
// externally visable type of the method has a type param
// inserted in between the trait type params and the
// method type params. The substs that we are given are
// the proper substs *internally* to the method body, so
// we have to use those when compiling it.
//
// In order to get the proper substitution to use on the
// type of the method, we pull apart the substitution and
// stick a substitution for the self type in.
// This is a bit unfortunate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is.


let idx = psubsts.tys.len() - num_method_ty_params;
let substs =
(psubsts.tys.slice(0, idx) +
&[psubsts.self_ty.get()] +
psubsts.tys.tailn(idx));
debug!("static default: changed substitution to %s",
substs.repr(ccx.tcx));

ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
}
};
let llfty = type_of_fn_from_ty(ccx, mono_ty);

ccx.stats.n_monos += 1;
Expand Down
61 changes: 40 additions & 21 deletions src/librustc/middle/trans/type_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub type type_uses = uint; // Bitmask
pub static use_repr: uint = 1; /* Dependency on size/alignment/mode and
take/drop glue */
pub static use_tydesc: uint = 2; /* Takes the tydesc, or compares */
pub static use_all: uint = use_repr|use_tydesc;


pub struct Context {
ccx: @mut CrateContext,
Expand All @@ -57,6 +59,14 @@ pub struct Context {

pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
-> @~[type_uses] {

fn store_type_uses(cx: Context, fn_id: def_id) -> @~[type_uses] {
let Context { uses, ccx } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
uses
}

match ccx.type_use_cache.find(&fn_id) {
Some(uses) => return *uses,
None => ()
Expand All @@ -65,32 +75,29 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
let fn_id_loc = if fn_id.crate == local_crate {
fn_id
} else {
inline::maybe_instantiate_inline(ccx, fn_id, true)
inline::maybe_instantiate_inline(ccx, fn_id)
};

// Conservatively assume full use for recursive loops
ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, 3u));
ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, use_all));

let cx = Context {
ccx: ccx,
uses: @mut vec::from_elem(n_tps, 0)
};
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for sig.inputs.iter().advance |arg| {
type_needs(&cx, use_repr, *arg);
}
}
_ => ()
}

if fn_id_loc.crate != local_crate {
let Context { uses, _ } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
return uses;
// If the method is a default method, we mark all of the types as
// used. This is imprecise, but simple. Getting it right is
// tricky because the substs on the call and the substs on the
// default method differ, because of substs on the trait/impl.
let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc);
// We also mark all of the params as used if it is an extern thing
// that we haven't been able to inline yet.
if is_default || fn_id_loc.crate != local_crate {
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all; }
return store_type_uses(cx, fn_id);
}

let map_node = match ccx.tcx.items.find(&fn_id_loc.node) {
Some(x) => (/*bad*/copy *x),
None => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
Expand All @@ -106,7 +113,10 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
// This will be a static trait method. For now, we just assume
// it fully depends on all of the type information. (Doing
// otherwise would require finding the actual implementation).
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr|use_tydesc;}
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all;}
// We need to return early, before the arguments are processed,
// because of difficulties in the handling of Self.
return store_type_uses(cx, fn_id);
}
ast_map::node_variant(_, _, _) => {
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
Expand Down Expand Up @@ -171,10 +181,19 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
token::get_ident_interner())));
}
}
let Context { uses, _ } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
uses

// Now handle arguments
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for sig.inputs.iter().advance |arg| {
type_needs(&cx, use_repr, *arg);
}
}
_ => ()
}

store_type_uses(cx, fn_id)
}

pub fn type_needs(cx: &Context, use_: uint, ty: ty::t) {
Expand Down
Loading