diff options
| -rw-r--r-- | src/rustc/middle/kind.rs | 21 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 27 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check/vtable.rs | 5 | ||||
| -rw-r--r-- | src/test/compile-fail/vtable-res-trait-param.rs | 23 |
4 files changed, 54 insertions, 22 deletions
diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 35675b9102b..15882d5e9fa 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -226,25 +226,8 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { _ => { // Type substitions should only occur on paths and // method calls, so this needs to be a method call. - match cx.method_map.get(e.id).origin { - typeck::method_static(did) => { - // n.b.: When we encode class/impl methods, the bounds - // that we encode include both the class/impl bounds - // and then the method bounds themselves... - ty::lookup_item_type(cx.tcx, did).bounds - } - typeck::method_param({trait_id:trt_id, - method_num:n_mth, _}) | - typeck::method_trait(trt_id, n_mth) => { - // ...trait methods bounds, in contrast, include only the - // method bounds, so we must preprend the tps from the - // trait itself. This ought to be harmonized. - let trt_bounds = - ty::lookup_item_type(cx.tcx, trt_id).bounds; - let mth = ty::trait_methods(cx.tcx, trt_id)[n_mth]; - @(vec::append(*trt_bounds, *mth.tps)) - } - } + ty::method_call_bounds(cx.tcx, cx.method_map, e.id).expect( + ~"non path/method call expr has type substs??") } }; if vec::len(ts) != vec::len(*bounds) { diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index fa6ca057602..bc74f654ca8 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -178,6 +178,7 @@ export eval_repeat_count; export fn_proto, proto_bare, proto_vstore; export ast_proto_to_proto; export is_blockish; +export method_call_bounds; // Data types @@ -2414,6 +2415,32 @@ fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool { return node_id_has_type_params(cx, expr.id); } +fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, + id: ast::node_id) + -> option<@~[param_bounds]> { + do method_map.find(id).map |method| { + match method.origin { + typeck::method_static(did) => { + // n.b.: When we encode class/impl methods, the bounds + // that we encode include both the class/impl bounds + // and then the method bounds themselves... + ty::lookup_item_type(tcx, did).bounds + } + typeck::method_param({trait_id:trt_id, + method_num:n_mth, _}) | + typeck::method_trait(trt_id, n_mth) => { + // ...trait methods bounds, in contrast, include only the + // method bounds, so we must preprend the tps from the + // trait itself. This ought to be harmonized. + let trt_bounds = + ty::lookup_item_type(tcx, trt_id).bounds; + let mth = ty::trait_methods(tcx, trt_id)[n_mth]; + @(vec::append(*trt_bounds, *mth.tps)) + } + } + } +} + fn expr_is_lval(method_map: typeck::method_map, e: @ast::expr) -> bool { match e.node { ast::expr_path(_) | ast::expr_unary(ast::deref, _) => true, diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index a0218f3e9b5..a3cd3c6c79e 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -252,9 +252,8 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) { ast::expr_index(*) => { debug!("(vtable - resolving expr) resolving field/binary/unary/\ assign/index expr"); - match cx.method_map.find(ex.id) { - some({origin: method_static(did), _}) => { - let bounds = ty::lookup_item_type(cx.tcx, did).bounds; + match ty::method_call_bounds(cx.tcx, cx.method_map, ex.id) { + some(bounds) => { if has_trait_bounds(*bounds) { let callee_id = match ex.node { ast::expr_field(_, _, _) => ex.id, diff --git a/src/test/compile-fail/vtable-res-trait-param.rs b/src/test/compile-fail/vtable-res-trait-param.rs new file mode 100644 index 00000000000..550be31d1a4 --- /dev/null +++ b/src/test/compile-fail/vtable-res-trait-param.rs @@ -0,0 +1,23 @@ +trait TraitA { + fn method_a() -> int; +} + +trait TraitB { + fn gimme_an_a<A: TraitA>(a: A) -> int; +} + +impl int: TraitB { + fn gimme_an_a<A: TraitA>(a: A) -> int { + a.method_a() + self + } +} + +fn call_it<B: TraitB>(b: B) -> int { + let y = 4u; + b.gimme_an_a(y) //~ ERROR failed to find an implementation of trait @TraitA for uint +} + +fn main() { + let x = 3i; + assert call_it(x) == 22; +} |
