Repository: rust
Issue: Diagnostic hints emitted on unresolved method calls that suggest qualified associated function calls don't account for more complex self types
Labels: A-diagnostics,A-associated-items,T-compiler,A-suggestion-diagnostics,D-invalid-suggestion

Uplifted from https://github.com/rust-lang/rust/pull/118911#discussion_r1434022632 and further noticed while reviewing #119957.

With “more complex self types” I mean self types like `Box<Self>`, `Rc<Self>` etc. & `feature(arbitrary_self_types)`, basically anything other than `Self`, `&&...Self` and `&mut &mut... Self`.

---

Given:

```rs
struct S;

trait TraitA { fn f(this: Box<Self>); }
trait TraitB { fn f(this: Box<Self>); }

impl TraitA for S { fn f(this: Box<Self>) {} }
impl TraitB for S { fn f(this: Box<Self>) {} }

fn main() {
    Box::new(S).f(); //~ ERROR no method named `f` found for struct `Box<S>` in the current scope [E0599]
}
```

We currently output:

```
error[E0599]: no method named `f` found for struct `Box<S>` in the current scope
  --> src/main.rs:10:17
   |
10 |     Box::new(S).f();
   |                 ^ this is an associated function, not a method
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: candidate #1 is defined in the trait `TraitA`
  --> src/main.rs:3:16
   |
3  | trait TraitA { fn f(this: Box<Self>); }
   |                ^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in the trait `TraitB`
  --> src/main.rs:4:16
   |
4  | trait TraitB { fn f(this: Box<Self>); }
   |                ^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
   |
10 |     <Box<S> as TraitA>::f(Box::new(S));
   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the associated function for candidate #2
   |
10 |     <Box<S> as TraitB>::f(Box::new(S));
   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

However, `<Box<S> as $Trait>::f(Box::new(S))` is not correct (`$Trait` ∊ {`TraitA`, `TraitB`}).
We should either suggest

```diff
  help: disambiguate the associated function for candidate #1
     |
- 10 |     <Box<S> as TraitA>::f(Box::new(S));
-    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 10 |     TraitA::f(Box::new(S));
+    |     ~~~~~~~~~~~~~~~~~~~~~~
  help: disambiguate the associated function for candidate #2
     |
- 10 |     <Box<S> as TraitB>::f(Box::new(S));
-    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 10 |     TraitB::f(Box::new(S));
+    |     ~~~~~~~~~~~~~~~~~~~~~~

```

or

```diff
  help: disambiguate the associated function for candidate #1
     |
- 10 |     <Box<S> as TraitA>::f(Box::new(S));
-    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 10 |     <S as TraitA>::f(Box::new(S));
+    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  help: disambiguate the associated function for candidate #2
     |
- 10 |     <Box<S> as TraitB>::f(Box::new(S));
-    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 10 |     <S as TraitB>::f(Box::new(S));
+    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

```

---

Given:

```rs
struct A;

trait M {
    fn f(_: Box<Self>);
}

impl M for A {
    fn f(_: Box<Self>) {}
}

fn main() {
    Box::new(A).f(); //~ ERROR no method named `f` found for struct `Box<A>` in the current scope [E0599]
}
```

We should output the following:

```diff
  error[E0599]: no method named `f` found for struct `Box<A>` in the current scope
    --> src/main.rs:12:17
     |
  12 |     Box::new(A).f();
     |     ------------^--
     |     |           |
     |     |           this is an associated function, not a method
-    |     help: use associated function syntax instead: `Box<A>::f()`
+    |     help: use associated function syntax instead: `A::f(Box::new(A))`
     |
     = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
  note: the candidate is defined in the trait `M`
    --> src/main.rs:4:5
     |
  4  |     fn f(_: Box<Self>);
     |     ^^^^^^^^^^^^^^^^^^^
  
```