Skip to content

Commit 1ee54a8

Browse files
committed
auto merge of #7725 : msullivan/rust/default-methods, r=pcwalton
r?
2 parents 96453eb + 3fa5203 commit 1ee54a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+185
-121
lines changed

src/librustc/metadata/encoder.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
791791
if len > 0u || should_inline {
792792
(ecx.encode_inlined_item)(
793793
ecx, ebml_w, impl_path,
794-
ii_method(local_def(parent_id), m));
794+
ii_method(local_def(parent_id), false, m));
795795
} else {
796796
encode_symbol(ecx, ebml_w, m.id);
797797
}
@@ -1123,21 +1123,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
11231123
}
11241124

11251125
provided(m) => {
1126-
// This is obviously a bogus assert but I don't think this
1127-
// ever worked before anyhow...near as I can tell, before
1128-
// we would emit two items.
1129-
if method_ty.explicit_self == sty_static {
1130-
tcx.sess.span_unimpl(
1131-
item.span,
1132-
fmt!("Method %s is both provided and static",
1133-
token::ident_to_str(&method_ty.ident)));
1126+
// If this is a static method, we've already encoded
1127+
// this.
1128+
if method_ty.explicit_self != sty_static {
1129+
encode_type_param_bounds(ebml_w, ecx,
1130+
&m.generics.ty_params);
11341131
}
1135-
encode_type_param_bounds(ebml_w, ecx,
1136-
&m.generics.ty_params);
11371132
encode_method_sort(ebml_w, 'p');
11381133
(ecx.encode_inlined_item)(
11391134
ecx, ebml_w, path,
1140-
ii_method(local_def(item.id), m));
1135+
ii_method(local_def(item.id), true, m));
11411136
}
11421137
}
11431138

src/librustc/middle/astencode.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
319319
match *ii {
320320
//hack: we're not dropping items
321321
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
322-
ast::ii_method(d, m) => ast::ii_method(d, fld.fold_method(m)),
322+
ast::ii_method(d, is_provided, m) =>
323+
ast::ii_method(d, is_provided, fld.fold_method(m)),
323324
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
324325
}
325326
}
@@ -340,7 +341,8 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
340341

341342
match ii {
342343
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
343-
ast::ii_method(d, m) => ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m)),
344+
ast::ii_method(d, is_provided, m) =>
345+
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
344346
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
345347
}
346348
}

src/librustc/middle/lint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
244244
LintSpec {
245245
lint: default_methods,
246246
desc: "allow default methods",
247-
default: deny
247+
default: allow
248248
}),
249249

250250
("unused_unsafe",

src/librustc/middle/mem_categorization.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ impl cmt_ {
11851185
}
11861186
}
11871187

1188-
impl Repr for cmt {
1188+
impl Repr for cmt_ {
11891189
fn repr(&self, tcx: ty::ctxt) -> ~str {
11901190
fmt!("{%s id:%d m:%? ty:%s}",
11911191
self.cat.repr(tcx),

src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
520520
let _icx = push_ctxt("trans_res_dtor");
521521
if !substs.is_empty() {
522522
let did = if did.crate != ast::local_crate {
523-
inline::maybe_instantiate_inline(ccx, did, true)
523+
inline::maybe_instantiate_inline(ccx, did)
524524
} else {
525525
did
526526
};

src/librustc/middle/trans/callee.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ pub fn trans_fn_ref_with_vtables(
250250
def_id: ast::def_id, // def id of fn
251251
ref_id: ast::node_id, // node id of use of fn; may be zero if N/A
252252
type_params: &[ty::t], // values for fn's ty params
253-
vtables: Option<typeck::vtable_res>)
253+
vtables: Option<typeck::vtable_res>) // vtables for the call
254254
-> FnData {
255255
//!
256256
//
@@ -361,8 +361,7 @@ pub fn trans_fn_ref_with_vtables(
361361
// def_id to the local id of the inlined copy.
362362
let def_id = {
363363
if def_id.crate != ast::local_crate {
364-
let may_translate = opt_impl_did.is_none();
365-
inline::maybe_instantiate_inline(ccx, def_id, may_translate)
364+
inline::maybe_instantiate_inline(ccx, def_id)
366365
} else {
367366
def_id
368367
}

src/librustc/middle/trans/common.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,6 @@ impl Repr for param_substs {
154154
}
155155
}
156156

157-
impl Repr for @param_substs {
158-
fn repr(&self, tcx: ty::ctxt) -> ~str {
159-
param_substs_to_str(*self, tcx)
160-
}
161-
}
162-
163157
// Function context. Every LLVM function we create will have one of
164158
// these.
165159
pub struct fn_ctxt_ {

src/librustc/middle/trans/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::def_id) -> ValueRef
159159
let contains_key = cx.const_values.contains_key(&def_id.node);
160160
if !ast_util::is_local(def_id) || !contains_key {
161161
if !ast_util::is_local(def_id) {
162-
def_id = inline::maybe_instantiate_inline(cx, def_id, true);
162+
def_id = inline::maybe_instantiate_inline(cx, def_id);
163163
}
164164
match cx.tcx.items.get_copy(&def_id.node) {
165165
ast_map::node_item(@ast::item {

src/librustc/middle/trans/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
956956
fn get_did(ccx: @mut CrateContext, did: ast::def_id)
957957
-> ast::def_id {
958958
if did.crate != ast::local_crate {
959-
inline::maybe_instantiate_inline(ccx, did, true)
959+
inline::maybe_instantiate_inline(ccx, did)
960960
} else {
961961
did
962962
}

src/librustc/middle/trans/inline.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ use syntax::ast;
2222
use syntax::ast_map::path_name;
2323
use syntax::ast_util::local_def;
2424

25-
// `translate` will be true if this function is allowed to translate the
26-
// item and false otherwise. Currently, this parameter is set to false when
27-
// translating default methods.
28-
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
29-
translate: bool)
25+
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id)
3026
-> ast::def_id {
3127
let _icx = push_ctxt("maybe_instantiate_inline");
3228
match ccx.external.find(&fn_id) {
@@ -59,7 +55,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
5955
csearch::found(ast::ii_item(item)) => {
6056
ccx.external.insert(fn_id, Some(item.id));
6157
ccx.stats.n_inlines += 1;
62-
if translate { trans_item(ccx, item); }
58+
trans_item(ccx, item);
6359
local_def(item.id)
6460
}
6561
csearch::found(ast::ii_foreign(item)) => {
@@ -81,19 +77,19 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
8177
_ => ccx.sess.bug("maybe_instantiate_inline: item has a \
8278
non-enum parent")
8379
}
84-
if translate { trans_item(ccx, item); }
80+
trans_item(ccx, item);
8581
local_def(my_id)
8682
}
8783
csearch::found_parent(_, _) => {
8884
ccx.sess.bug("maybe_get_item_ast returned a found_parent \
8985
with a non-item parent");
9086
}
91-
csearch::found(ast::ii_method(impl_did, mth)) => {
87+
csearch::found(ast::ii_method(impl_did, is_provided, mth)) => {
9288
ccx.stats.n_inlines += 1;
9389
ccx.external.insert(fn_id, Some(mth.id));
9490
// If this is a default method, we can't look up the
9591
// impl type. But we aren't going to translate anyways, so don't.
96-
if !translate { return local_def(mth.id); }
92+
if is_provided { return local_def(mth.id); }
9793

9894
let impl_tpt = ty::lookup_item_type(ccx.tcx, impl_did);
9995
let num_type_params =

src/librustc/middle/trans/monomorphize.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,24 +63,26 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
6363
assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
6464
let _icx = push_ctxt("monomorphic_fn");
6565
let mut must_cast = false;
66-
let substs = real_substs.tps.iter().transform(|t| {
66+
67+
let do_normalize = |t: &ty::t| {
6768
match normalize_for_monomorphization(ccx.tcx, *t) {
6869
Some(t) => { must_cast = true; t }
6970
None => *t
7071
}
71-
}).collect::<~[ty::t]>();
72-
73-
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
74-
for substs.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
75-
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
72+
};
7673

7774
let psubsts = @param_substs {
78-
tys: substs,
75+
tys: real_substs.tps.map(|x| do_normalize(x)),
7976
vtables: vtables,
80-
self_ty: real_substs.self_ty,
77+
self_ty: real_substs.self_ty.map(|x| do_normalize(x)),
8178
self_vtable: self_vtable
8279
};
8380

81+
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
82+
for psubsts.tys.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
83+
let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len());
84+
85+
8486
let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
8587
&*psubsts,
8688
Some(param_uses));
@@ -109,6 +111,10 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
109111
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
110112
let llitem_ty = tpt.ty;
111113

114+
// We need to do special handling of the substitutions if we are
115+
// calling a static provided method. This is sort of unfortunate.
116+
let mut is_static_provided = None;
117+
112118
let map_node = session::expect(
113119
ccx.sess,
114120
ccx.tcx.items.find_copy(&fn_id.node),
@@ -127,6 +133,12 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
127133
return (get_item_val(ccx, fn_id.node), true);
128134
}
129135
ast_map::node_trait_method(@ast::provided(m), _, pt) => {
136+
// If this is a static provided method, indicate that
137+
// and stash the number of params on the method.
138+
if m.explicit_self.node == ast::sty_static {
139+
is_static_provided = Some(m.generics.ty_params.len());
140+
}
141+
130142
(pt, m.ident, m.span)
131143
}
132144
ast_map::node_trait_method(@ast::required(_), _, _) => {
@@ -151,8 +163,36 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
151163
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
152164
};
153165

154-
let mono_ty = ty::subst_tps(ccx.tcx, psubsts.tys,
155-
psubsts.self_ty, llitem_ty);
166+
debug!("monomorphic_fn about to subst into %s", llitem_ty.repr(ccx.tcx));
167+
let mono_ty = match is_static_provided {
168+
None => ty::subst_tps(ccx.tcx, psubsts.tys,
169+
psubsts.self_ty, llitem_ty),
170+
Some(num_method_ty_params) => {
171+
// Static default methods are a little unfortunate, in
172+
// that the "internal" and "external" type of them differ.
173+
// Internally, the method body can refer to Self, but the
174+
// externally visable type of the method has a type param
175+
// inserted in between the trait type params and the
176+
// method type params. The substs that we are given are
177+
// the proper substs *internally* to the method body, so
178+
// we have to use those when compiling it.
179+
//
180+
// In order to get the proper substitution to use on the
181+
// type of the method, we pull apart the substitution and
182+
// stick a substitution for the self type in.
183+
// This is a bit unfortunate.
184+
185+
let idx = psubsts.tys.len() - num_method_ty_params;
186+
let substs =
187+
(psubsts.tys.slice(0, idx) +
188+
&[psubsts.self_ty.get()] +
189+
psubsts.tys.tailn(idx));
190+
debug!("static default: changed substitution to %s",
191+
substs.repr(ccx.tcx));
192+
193+
ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
194+
}
195+
};
156196
let llfty = type_of_fn_from_ty(ccx, mono_ty);
157197

158198
ccx.stats.n_monos += 1;

src/librustc/middle/trans/type_use.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub type type_uses = uint; // Bitmask
4949
pub static use_repr: uint = 1; /* Dependency on size/alignment/mode and
5050
take/drop glue */
5151
pub static use_tydesc: uint = 2; /* Takes the tydesc, or compares */
52+
pub static use_all: uint = use_repr|use_tydesc;
53+
5254

5355
pub struct Context {
5456
ccx: @mut CrateContext,
@@ -57,6 +59,14 @@ pub struct Context {
5759

5860
pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
5961
-> @~[type_uses] {
62+
63+
fn store_type_uses(cx: Context, fn_id: def_id) -> @~[type_uses] {
64+
let Context { uses, ccx } = cx;
65+
let uses = @copy *uses; // freeze
66+
ccx.type_use_cache.insert(fn_id, uses);
67+
uses
68+
}
69+
6070
match ccx.type_use_cache.find(&fn_id) {
6171
Some(uses) => return *uses,
6272
None => ()
@@ -65,32 +75,29 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
6575
let fn_id_loc = if fn_id.crate == local_crate {
6676
fn_id
6777
} else {
68-
inline::maybe_instantiate_inline(ccx, fn_id, true)
78+
inline::maybe_instantiate_inline(ccx, fn_id)
6979
};
7080

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

7484
let cx = Context {
7585
ccx: ccx,
7686
uses: @mut vec::from_elem(n_tps, 0)
7787
};
78-
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
79-
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
80-
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
81-
for sig.inputs.iter().advance |arg| {
82-
type_needs(&cx, use_repr, *arg);
83-
}
84-
}
85-
_ => ()
86-
}
8788

88-
if fn_id_loc.crate != local_crate {
89-
let Context { uses, _ } = cx;
90-
let uses = @copy *uses; // freeze
91-
ccx.type_use_cache.insert(fn_id, uses);
92-
return uses;
89+
// If the method is a default method, we mark all of the types as
90+
// used. This is imprecise, but simple. Getting it right is
91+
// tricky because the substs on the call and the substs on the
92+
// default method differ, because of substs on the trait/impl.
93+
let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc);
94+
// We also mark all of the params as used if it is an extern thing
95+
// that we haven't been able to inline yet.
96+
if is_default || fn_id_loc.crate != local_crate {
97+
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all; }
98+
return store_type_uses(cx, fn_id);
9399
}
100+
94101
let map_node = match ccx.tcx.items.find(&fn_id_loc.node) {
95102
Some(x) => (/*bad*/copy *x),
96103
None => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
@@ -106,7 +113,10 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
106113
// This will be a static trait method. For now, we just assume
107114
// it fully depends on all of the type information. (Doing
108115
// otherwise would require finding the actual implementation).
109-
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr|use_tydesc;}
116+
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all;}
117+
// We need to return early, before the arguments are processed,
118+
// because of difficulties in the handling of Self.
119+
return store_type_uses(cx, fn_id);
110120
}
111121
ast_map::node_variant(_, _, _) => {
112122
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
@@ -171,10 +181,19 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
171181
token::get_ident_interner())));
172182
}
173183
}
174-
let Context { uses, _ } = cx;
175-
let uses = @copy *uses; // freeze
176-
ccx.type_use_cache.insert(fn_id, uses);
177-
uses
184+
185+
// Now handle arguments
186+
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
187+
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
188+
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
189+
for sig.inputs.iter().advance |arg| {
190+
type_needs(&cx, use_repr, *arg);
191+
}
192+
}
193+
_ => ()
194+
}
195+
196+
store_type_uses(cx, fn_id)
178197
}
179198

180199
pub fn type_needs(cx: &Context, use_: uint, ty: ty::t) {

0 commit comments

Comments
 (0)