diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-11-01 15:08:36 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-11-01 15:10:41 -0700 |
| commit | 94f05c1936e85d4805e7177fe546d4c6f40340d8 (patch) | |
| tree | 06d3875f263ce585c99a3e031c2e284a8533fa28 /src/rustc | |
| parent | 3d8df9947fae1c55a1de9b461ae142059c1edcac (diff) | |
| download | rust-94f05c1936e85d4805e7177fe546d4c6f40340d8.tar.gz rust-94f05c1936e85d4805e7177fe546d4c6f40340d8.zip | |
rustc: Stop overwriting trait static method types when checking generic trait refs. Closes #3903. rs=blocking-burg
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/middle/typeck/check/vtable.rs | 13 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/collect.rs | 27 |
2 files changed, 34 insertions, 6 deletions
diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index 85a65d7432f..bfd6d5a44e8 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -100,6 +100,10 @@ fn lookup_vtable_covariant(fcx: @fn_ctxt, allow_unsafe: bool, is_early: bool) -> Option<vtable_origin> { + debug!("lookup_vtable_covariant(ty: %s, trait_ty=%s)", + fcx.infcx().ty_to_str(ty), + fcx.infcx().ty_to_str(trait_ty)); + let worklist = dvec::DVec(); worklist.push(trait_ty); while worklist.len() > 0 { @@ -475,9 +479,16 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) { ast::expr_path(*) => { match fcx.opt_node_ty_substs(ex.id) { Some(ref substs) => { - let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id)); + let def = cx.tcx.def_map.get(ex.id); + let did = ast_util::def_id_of_def(def); + debug!("early resolve expr: def %?", def); let item_ty = ty::lookup_item_type(cx.tcx, did); if has_trait_bounds(*item_ty.bounds) { + for item_ty.bounds.each |bounds| { + debug!("early_resolve_expr: looking up vtables for bound \ + %s", + ty::param_bounds_to_str(fcx.tcx(), *bounds)); + } let vtbls = lookup_vtables(fcx, ex, item_ty.bounds, substs, false, is_early); if !is_early { cx.vtable_map.insert(ex.id, vtbls); } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index ed0cd48504b..ca12e355636 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -231,10 +231,11 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { let trait_bounds = ty_param_bounds(ccx, params); let ty_m = trait_method_to_ty_method(*m); let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); - if ty_m.self_ty.node == ast::sty_static { - make_static_method_ty(ccx, ty_m, region_paramd, - method_ty, trait_ty, trait_bounds); - } + if ty_m.self_ty.node == ast::sty_static { + make_static_method_ty(ccx, ty_m, region_paramd, + method_ty, trait_ty, + trait_bounds); + } method_ty }); } @@ -420,9 +421,25 @@ fn check_methods_against_trait(ccx: @crate_ctxt, let tcx = ccx.tcx; let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp); + if did.crate == ast::local_crate { - ensure_trait_methods(ccx, did.node, tpt.ty); + // NB: This is subtle. We need to do this on the type of the trait + // item *itself*, not on the type that includes the parameter + // substitutions provided by the programmer at this particular + // trait ref. Otherwise, we will potentially overwrite the types of + // the methods within the trait with bogus results. (See issue #3903.) + + match tcx.items.find(did.node) { + Some(ast_map::node_item(item, _)) => { + let tpt = ty_of_item(ccx, item); + ensure_trait_methods(ccx, did.node, tpt.ty); + } + _ => { + tcx.sess.bug(~"trait ref didn't resolve to trait"); + } + } } + for vec::each(*ty::trait_methods(tcx, did)) |trait_m| { match vec::find(impl_ms, |impl_m| trait_m.ident == impl_m.mty.ident) { Some(ref cm) => { |
