Skip to content

Commit c0858f4

Browse files
committed
In typeck::collect::ensure_trait_methods, don't assume the trait was already checked
Instead of using node_id_to_type to look up the trait type, pass it in as an argument. This handles the case where we check an impl of a trait T before T has been traversed.
1 parent 55ee06b commit c0858f4

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

src/rustc/middle/typeck/collect.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,18 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
156156
}
157157
}
158158

159-
fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
159+
fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
160160
fn store_methods<T>(ccx: @crate_ctxt, id: ast::node_id,
161161
stuff: ~[T], f: fn@(T) -> ty::method) {
162162
ty::store_trait_methods(ccx.tcx, id, @vec::map(stuff, f));
163163
}
164164

165-
fn make_static_method_ty(ccx: @crate_ctxt, id: ast::node_id,
165+
fn make_static_method_ty(ccx: @crate_ctxt,
166166
am: ast::ty_method,
167167
rp: bool, m: ty::method,
168+
// Take this as an argument b/c we may check
169+
// the impl before the trait.
170+
trait_ty: ty::t,
168171
trait_bounds: @~[ty::param_bounds]) {
169172
// We need to create a typaram that replaces self. This param goes
170173
// *in between* the typarams from the trait and those from the
@@ -188,7 +191,6 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
188191
let substs = { self_r: none, self_ty: some(self_param),
189192
tps: non_shifted_trait_tps + shifted_method_tps };
190193
let ty = ty::subst(ccx.tcx, &substs, ty::mk_fn(ccx.tcx, m.fty));
191-
let trait_ty = ty::node_id_to_type(ccx.tcx, id);
192194
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
193195
+ *m.tps);
194196
ccx.tcx.tcache.insert(local_def(am.id),
@@ -205,8 +207,8 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
205207
let ty_m = trait_method_to_ty_method(m);
206208
let method_ty = ty_of_ty_method(ccx, ty_m, rp);
207209
if ty_m.self_ty.node == ast::sty_static {
208-
make_static_method_ty(ccx, id, ty_m, rp,
209-
method_ty, trait_bounds);
210+
make_static_method_ty(ccx, ty_m, rp,
211+
method_ty, trait_ty, trait_bounds);
210212
}
211213
method_ty
212214
});
@@ -319,7 +321,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
319321
let tcx = ccx.tcx;
320322
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp);
321323
if did.crate == ast::local_crate {
322-
ensure_trait_methods(ccx, did.node);
324+
ensure_trait_methods(ccx, did.node, tpt.ty);
323325
}
324326
for vec::each(*ty::trait_methods(tcx, did)) |trait_m| {
325327
match vec::find(impl_ms, |impl_m| trait_m.ident == impl_m.mty.ident) {
@@ -430,7 +432,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
430432
debug!{"item_trait(it.id=%d, tpt.ty=%s)",
431433
it.id, ty_to_str(tcx, tpt.ty)};
432434
write_ty_to_tcx(tcx, it.id, tpt.ty);
433-
ensure_trait_methods(ccx, it.id);
435+
ensure_trait_methods(ccx, it.id, tpt.ty);
434436

435437
let (_, provided_methods) = split_trait_methods(trait_methods);
436438
let selfty = ty::mk_self(tcx);
@@ -499,7 +501,7 @@ fn convert_struct(ccx: @crate_ctxt, rp: bool, struct_def: @ast::struct_def,
499501
rp: rp,
500502
ty: t_dtor});
501503
};
502-
ensure_trait_methods(ccx, id);
504+
ensure_trait_methods(ccx, id, tpt.ty);
503505

504506
// Write the type of each of the members
505507
let (fields, methods) = split_class_items(struct_def.members);

src/test/run-pass/trait-mix.rc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod trait_mix {
2+
#[path = "trait-mix.rs"]
3+
mod trait_mix;
4+
mod u_trait_mix;
5+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import u_trait_mix;
2+
3+
impl f32: u_trait_mix::num {
4+
pure fn add(&&other: f32) -> f32 { return self + other; }
5+
pure fn sub(&&other: f32) -> f32 { return self - other; }
6+
pure fn mul(&&other: f32) -> f32 { return self * other; }
7+
pure fn div(&&other: f32) -> f32 { return self / other; }
8+
pure fn modulo(&&other: f32) -> f32 { return self % other; }
9+
pure fn neg() -> f32 { return -self; }
10+
11+
pure fn to_int() -> int { return self as int; }
12+
static pure fn from_int(n: int) -> f32 { return n as f32; }
13+
}
14+
15+
/*
16+
It seems that this will fail if I try using it from another crate.
17+
18+
*/
19+
20+
/*
21+
22+
// ICEs if I put this in num -- ???
23+
trait from_int {
24+
25+
}
26+
*/
27+
28+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait num {
2+
// FIXME: Trait composition. (#2616)
3+
pure fn add(&&other: self) -> self;
4+
pure fn sub(&&other: self) -> self;
5+
pure fn mul(&&other: self) -> self;
6+
pure fn div(&&other: self) -> self;
7+
pure fn modulo(&&other: self) -> self;
8+
pure fn neg() -> self;
9+
10+
pure fn to_int() -> int;
11+
static pure fn from_int(n: int) -> self;
12+
}
13+

0 commit comments

Comments
 (0)