Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicit borrows and typeclasses interact inconsistently #2796

Closed
msullivan opened this issue Jul 3, 2012 · 3 comments
Closed

Implicit borrows and typeclasses interact inconsistently #2796

msullivan opened this issue Jul 3, 2012 · 3 comments
Labels
A-lifetimes Area: Lifetimes / regions A-type-system Area: Type system

Comments

@msullivan
Copy link
Contributor

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.

@ghost ghost assigned msullivan Jul 3, 2012
@nikomatsakis
Copy link
Contributor

Yes, I've been worried about this. Perhaps removing the implicit borrows for method calls is the right thing to do.

@nikomatsakis
Copy link
Contributor

After more thought, I don't think removing the implicit borrows for receivers is the right thing, or at least it's not the whole story. For example, if I define a class T and I define methods on &T, I would like to be able to use those methods on an instance of type @T. But this requires the implicit borrows for receivers.

@msullivan
Copy link
Contributor Author

I think that, for now, I am going to make method resolution only try type assignability if it couldn't find an instance just using subtyping. I'm not super excited about this, since I want method calls to become less magical, not more, but it seems reasonably analogous to autoderefing one level at a time when searching, and allows a workaround for this problem.

@msullivan msullivan removed their assignment Jun 16, 2014
celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
Upgrade CBMC version to latest (5.93.0).

Resolves rust-lang#2650
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions A-type-system Area: Type system
Projects
None yet
Development

No branches or pull requests

2 participants