Missing field resolve error doesn't look at associated functions (original) (raw)
Code
struct S; impl S { fn foo() {} fn bar(&self) { self.foo(); let f: fn() = self.foo; } }
Current output
error[E0599]: no method named foo found for reference &S in the current scope
--> src/lib.rs:5:14
|
5 | self.foo();
| -----^^^--
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: S::foo()
|
= note: found the following associated functions; to be used as methods, functions must have a self parameter
note: the candidate is defined in an impl for the type S
--> src/lib.rs:3:5
|
3 | fn foo() {}
| ^^^^^^^^
error[E0609]: no field foo on type &S
--> src/lib.rs:6:28
|
6 | let f: fn() = self.foo;
| ^^^ unknown field
Desired output
error[E0599]: no method named foo found for reference &S in the current scope
--> src/lib.rs:5:14
|
5 | self.foo();
| ^^^ 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: the candidate is defined in an impl for the type S
--> src/lib.rs:3:5
|
3 | fn foo() {}
| ^^^^^^^^
help: use associated function syntax instead
--> src/lib.rs:5:14
|
5 - self.foo();
5 + Self::foo();
|
error[E0609]: no field foo on type &S
--> src/lib.rs:6:28
|
6 | let f: fn() = self.foo;
| ^^^ 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: the candidate is defined in an impl for the type S
--> src/lib.rs:3:5
|
3 | fn foo() {}
| ^^^^^^^^
help: use associated function syntax instead
--> src/lib.rs:5:14
|
6 - let f: fn() = self.foo;
6 + let f: fn() = Self::foo;
|
Rationale and extra context
The structured suggestion should be verbose instead of inline, to make it clearer what we want the user to write.
The second case doesn't look for associated functions, because the syntax is quite far from what it needs to be, so it never occurred to us that there are cases where it is appropriate to do so. Sadly, this happens during resolve, so we are limited in how much we can explore the expression's context to figure out if an fn pointer is desired to begin with. On the other hand, this can be a two-fold typo, where someone wanted Self::foo() instead of self.foo and forgot the parentheses. The mention of the associated function should be the last fallback for field access resolve error, as it is the least likely thing the user intended.
Other cases
Rust Version
Build using the Nightly version: 1.93.0-nightly
(2025-11-16 518b428304e0008859cb)
Anything else?
Noted by https://social.linux.pizza/@jamesthebard/115566259453362334