_ => {
// 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) {
export fn_proto, proto_bare, proto_vstore;
export ast_proto_to_proto;
export is_blockish;
+export method_call_bounds;
// Data types
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,
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,
--- /dev/null
+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;
+}