Skip to content

Commit 94f05c1

Browse files
committed
rustc: Stop overwriting trait static method types when checking generic trait refs. Closes #3903. rs=blocking-burg
1 parent 3d8df99 commit 94f05c1

File tree

3 files changed

+66
-6
lines changed

3 files changed

+66
-6
lines changed

src/rustc/middle/typeck/check/vtable.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ fn lookup_vtable_covariant(fcx: @fn_ctxt,
100100
allow_unsafe: bool,
101101
is_early: bool)
102102
-> Option<vtable_origin> {
103+
debug!("lookup_vtable_covariant(ty: %s, trait_ty=%s)",
104+
fcx.infcx().ty_to_str(ty),
105+
fcx.infcx().ty_to_str(trait_ty));
106+
103107
let worklist = dvec::DVec();
104108
worklist.push(trait_ty);
105109
while worklist.len() > 0 {
@@ -475,9 +479,16 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
475479
ast::expr_path(*) => {
476480
match fcx.opt_node_ty_substs(ex.id) {
477481
Some(ref substs) => {
478-
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
482+
let def = cx.tcx.def_map.get(ex.id);
483+
let did = ast_util::def_id_of_def(def);
484+
debug!("early resolve expr: def %?", def);
479485
let item_ty = ty::lookup_item_type(cx.tcx, did);
480486
if has_trait_bounds(*item_ty.bounds) {
487+
for item_ty.bounds.each |bounds| {
488+
debug!("early_resolve_expr: looking up vtables for bound \
489+
%s",
490+
ty::param_bounds_to_str(fcx.tcx(), *bounds));
491+
}
481492
let vtbls = lookup_vtables(fcx, ex, item_ty.bounds,
482493
substs, false, is_early);
483494
if !is_early { cx.vtable_map.insert(ex.id, vtbls); }

src/rustc/middle/typeck/collect.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,11 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
231231
let trait_bounds = ty_param_bounds(ccx, params);
232232
let ty_m = trait_method_to_ty_method(*m);
233233
let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
234-
if ty_m.self_ty.node == ast::sty_static {
235-
make_static_method_ty(ccx, ty_m, region_paramd,
236-
method_ty, trait_ty, trait_bounds);
237-
}
234+
if ty_m.self_ty.node == ast::sty_static {
235+
make_static_method_ty(ccx, ty_m, region_paramd,
236+
method_ty, trait_ty,
237+
trait_bounds);
238+
}
238239
method_ty
239240
});
240241
}
@@ -420,9 +421,25 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
420421
421422
let tcx = ccx.tcx;
422423
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp);
424+
423425
if did.crate == ast::local_crate {
424-
ensure_trait_methods(ccx, did.node, tpt.ty);
426+
// NB: This is subtle. We need to do this on the type of the trait
427+
// item *itself*, not on the type that includes the parameter
428+
// substitutions provided by the programmer at this particular
429+
// trait ref. Otherwise, we will potentially overwrite the types of
430+
// the methods within the trait with bogus results. (See issue #3903.)
431+
432+
match tcx.items.find(did.node) {
433+
Some(ast_map::node_item(item, _)) => {
434+
let tpt = ty_of_item(ccx, item);
435+
ensure_trait_methods(ccx, did.node, tpt.ty);
436+
}
437+
_ => {
438+
tcx.sess.bug(~"trait ref didn't resolve to trait");
439+
}
440+
}
425441
}
442+
426443
for vec::each(*ty::trait_methods(tcx, did)) |trait_m| {
427444
match vec::find(impl_ms, |impl_m| trait_m.ident == impl_m.mty.ident) {
428445
Some(ref cm) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
mod base {
2+
pub trait HasNew<T> {
3+
static pure fn new() -> T;
4+
}
5+
6+
pub struct Foo {
7+
dummy: (),
8+
}
9+
10+
pub impl Foo : base::HasNew<Foo> {
11+
static pure fn new() -> Foo {
12+
unsafe { io::println("Foo"); }
13+
Foo { dummy: () }
14+
}
15+
}
16+
17+
pub struct Bar {
18+
dummy: (),
19+
}
20+
21+
pub impl Bar : base::HasNew<Bar> {
22+
static pure fn new() -> Bar {
23+
unsafe { io::println("Bar"); }
24+
Bar { dummy: () }
25+
}
26+
}
27+
}
28+
29+
fn main() {
30+
let f: base::Foo = base::new::<base::Foo, base::Foo>();
31+
let b: base::Bar = base::new::<base::Bar, base::Bar>();
32+
}

0 commit comments

Comments
 (0)