Closed
Description
Vtable resolution ignores calls to methods on type parameters or traits. If the methods themselves take bounded type parameters, this leads to ICEs in trans because the requisite information is not found.
Consider this example:
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)
}
fn main() {
let x = 3i;
assert call_it(x) == 22;
}
Here, the call_it()
function should not compile, because gimme_an_a()
demands a type which implements the interface TraitA
---of which there are no implementations! Still it compiles. Bad.
The relevant code is in rustc::middle::typeck::check::vtable::resolve_expr()
, which ignores all cases other than method_static
:
ast::expr_field(*) | ast::expr_binary(*) |
ast::expr_unary(*) | ast::expr_assign_op(*) |
ast::expr_index(*) => {
match cx.method_map.find(ex.id) {
some({origin: method_static(did), _}) => {
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
if has_trait_bounds(*bounds) {
let callee_id = match ex.node {
ast::expr_field(_, _, _) => ex.id,
_ => ex.callee_id
};
let substs = fcx.node_ty_substs(callee_id);
cx.vtable_map.insert(
callee_id,
lookup_vtables(fcx, ex, bounds,
&substs, false));
}
}
_ => ()
}
}