Skip to content

Commit a14485b

Browse files
committed
Do vtable resolution for *all* method calls, not just statically resolved ones... Closes #3221.
1 parent 1300be5 commit a14485b

File tree

4 files changed

+54
-22
lines changed

4 files changed

+54
-22
lines changed

src/rustc/middle/kind.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -226,25 +226,8 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
226226
_ => {
227227
// Type substitions should only occur on paths and
228228
// method calls, so this needs to be a method call.
229-
match cx.method_map.get(e.id).origin {
230-
typeck::method_static(did) => {
231-
// n.b.: When we encode class/impl methods, the bounds
232-
// that we encode include both the class/impl bounds
233-
// and then the method bounds themselves...
234-
ty::lookup_item_type(cx.tcx, did).bounds
235-
}
236-
typeck::method_param({trait_id:trt_id,
237-
method_num:n_mth, _}) |
238-
typeck::method_trait(trt_id, n_mth) => {
239-
// ...trait methods bounds, in contrast, include only the
240-
// method bounds, so we must preprend the tps from the
241-
// trait itself. This ought to be harmonized.
242-
let trt_bounds =
243-
ty::lookup_item_type(cx.tcx, trt_id).bounds;
244-
let mth = ty::trait_methods(cx.tcx, trt_id)[n_mth];
245-
@(vec::append(*trt_bounds, *mth.tps))
246-
}
247-
}
229+
ty::method_call_bounds(cx.tcx, cx.method_map, e.id).expect(
230+
~"non path/method call expr has type substs??")
248231
}
249232
};
250233
if vec::len(ts) != vec::len(*bounds) {

src/rustc/middle/ty.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export eval_repeat_count;
178178
export fn_proto, proto_bare, proto_vstore;
179179
export ast_proto_to_proto;
180180
export is_blockish;
181+
export method_call_bounds;
181182

182183
// Data types
183184

@@ -2414,6 +2415,32 @@ fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
24142415
return node_id_has_type_params(cx, expr.id);
24152416
}
24162417
2418+
fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
2419+
id: ast::node_id)
2420+
-> option<@~[param_bounds]> {
2421+
do method_map.find(id).map |method| {
2422+
match method.origin {
2423+
typeck::method_static(did) => {
2424+
// n.b.: When we encode class/impl methods, the bounds
2425+
// that we encode include both the class/impl bounds
2426+
// and then the method bounds themselves...
2427+
ty::lookup_item_type(tcx, did).bounds
2428+
}
2429+
typeck::method_param({trait_id:trt_id,
2430+
method_num:n_mth, _}) |
2431+
typeck::method_trait(trt_id, n_mth) => {
2432+
// ...trait methods bounds, in contrast, include only the
2433+
// method bounds, so we must preprend the tps from the
2434+
// trait itself. This ought to be harmonized.
2435+
let trt_bounds =
2436+
ty::lookup_item_type(tcx, trt_id).bounds;
2437+
let mth = ty::trait_methods(tcx, trt_id)[n_mth];
2438+
@(vec::append(*trt_bounds, *mth.tps))
2439+
}
2440+
}
2441+
}
2442+
}
2443+
24172444
fn expr_is_lval(method_map: typeck::method_map, e: @ast::expr) -> bool {
24182445
match e.node {
24192446
ast::expr_path(_) | ast::expr_unary(ast::deref, _) => true,

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,8 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
252252
ast::expr_index(*) => {
253253
debug!("(vtable - resolving expr) resolving field/binary/unary/\
254254
assign/index expr");
255-
match cx.method_map.find(ex.id) {
256-
some({origin: method_static(did), _}) => {
257-
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
255+
match ty::method_call_bounds(cx.tcx, cx.method_map, ex.id) {
256+
some(bounds) => {
258257
if has_trait_bounds(*bounds) {
259258
let callee_id = match ex.node {
260259
ast::expr_field(_, _, _) => ex.id,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
trait TraitA {
2+
fn method_a() -> int;
3+
}
4+
5+
trait TraitB {
6+
fn gimme_an_a<A: TraitA>(a: A) -> int;
7+
}
8+
9+
impl int: TraitB {
10+
fn gimme_an_a<A: TraitA>(a: A) -> int {
11+
a.method_a() + self
12+
}
13+
}
14+
15+
fn call_it<B: TraitB>(b: B) -> int {
16+
let y = 4u;
17+
b.gimme_an_a(y) //~ ERROR failed to find an implementation of trait @TraitA for uint
18+
}
19+
20+
fn main() {
21+
let x = 3i;
22+
assert call_it(x) == 22;
23+
}

0 commit comments

Comments
 (0)