- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
The interaction between implicit borrows and typeclasses is currently problematic and inconsistent.
Suppose we have the following interface, an implementation of it for vector slices, and a function that is parameterized over the typeclass:
iface iterable<A> {
    fn iterate(blk: fn(A) -> bool);
}
impl vec/&<A> of iterable<A> for &[const A] {
    fn iterate(f: fn(A) -> bool) {
        vec::each(self, f);
    }
}
fn print<A, T: iterable<A>>(x: T) {
    for x.iterate() |x| { log(error, x); }
}
The following code works since x will be implicitly borrowed
fn main() {
    let x = ~[1,2,3];
    for x.iterate() |x| { log(error, x) }
}
This is because add_candidates_from_scope in method.rs uses can_mk_assignty when matching against impls, which will do a borrow to convert x to a slice.
However, the following code does not work:
fn main() {
    let x = ~[1,2,3];
    print(x);
}
It will fail to find an implementation of iterable for [int]/~. This is because lookup_vtable in vtable.rs uses mk_subty when matching against impls. I think that lookup_vtable basically has to use subtyping and not type assignability: typeclass constraints need not correspond to just the type of an argument expression that we can perform a borrow on.
To make matters worse, we can't work around this by just writing impls for ~[A], since then the first example would fail with an error about multiple methods in scope.
I think probably the right thing to do is to not do implicit borrows on method calls, but I'm not sure.