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

Method call resolution documentation is wrong #1321

Closed
tczajka opened this issue Jan 23, 2023 · 1 comment
Closed

Method call resolution documentation is wrong #1321

tczajka opened this issue Jan 23, 2023 · 1 comment

Comments

@tczajka
Copy link
Contributor

tczajka commented Jan 23, 2023

I am looking at the algorithm for method call resolution.

The first step is to build a list of candidate receiver types. Obtain these by repeatedly dereferencing the receiver expression's type, adding each type encountered to the list, then finally attempting an unsized coercion at the end, and adding the result type if that is successful. Then, for each candidate T, add &T and &mut T to the list immediately after T.

For instance, if the receiver has type Box<[i32;2]>, then the candidate types will be Box<[i32;2]>, &Box<[i32;2]>, &mut Box<[i32;2]>, [i32; 2] (by dereferencing), &[i32; 2], &mut [i32; 2], [i32] (by unsized coercion), &[i32], and finally &mut [i32].

Then, for each candidate type T, search for a visible method with a receiver of that type in the following places:

  1. T's inherent methods (methods implemented directly on T).
  2. Any of the methods provided by a visible trait implemented by T. If T is a type parameter, methods provided by trait bounds on T are looked up first. Then all remaining methods in scope are looked up.

Let's follow this algorithm for this method call:

struct Foo;

impl Foo {
    fn foo(&self) {}
}

fn main() {
    let a = Foo;
    a.foo();
}

First, build the list of candidate types:

  1. Foo
  2. &Foo
  3. &mut Foo

Then for each candidate type, search for methods with a receiver of that type in the places listed:

  1. Foo: There are no methods with receiver type of Foo
  2. &Foo:
    2.1. Search &Foo's inherent methods (methods implemented directly on &Foo). There are none because there is no impl &Foo.
    2.2. Search methods provided by traits implemented by &Foo. There are none.
  3. &mut Foo: no methods with receiver type of &mut Foo

So according to the reference, the a.foo() method call shouldn't work.

Another example is with a trait:

struct Foo;

trait Trait {
    fn foo(&self);
}

impl Trait for Foo {
    fn foo(&self) {}
}

fn main() {
    let a = Foo;
    a.foo();
}

The reference says to look for methods with the receiver type of &Foo in traits implemented by &Foo, but Trait is not implemented by &Foo.

@ehuss
Copy link
Contributor

ehuss commented Jan 23, 2023

Thanks for the report! Yea, the method call algorithm needs updating. That is tracked in #1018, so closing as a duplicate of that.

@ehuss ehuss closed this as not planned Won't fix, can't repro, duplicate, stale Jan 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants