-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
A minimized example, derived from a chain of changes that a friend (who has just begun learning Rust) did.
Starting from this code (Playground link):
fn main() {
let x = "".chars().collect();
}The current output is:
error[E0282]: type annotations needed
--> src/main.rs:2:9
|
2 | let x = "".chars().collect();
| ^
|
help: consider giving `x` an explicit type
|
2 | let x: _ = "".chars().collect();
| +++
Now someone more familiar with Rust wouldn't just blindly add a : _ (since it doesn't lead to telling Rust anything new here, just would move the problem), but this friend is new to Rust, and has often found suggestions in the "help:" section to immediately provide fixes, so they add the : _, making the code into this (Playground link):
fn main() {
let x: _ = "".chars().collect();
}The current output for this is:
error[E0282]: type annotations needed
--> src/main.rs:2:27
|
2 | let x: _ = "".chars().collect();
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect`
|
help: consider specifying the generic argument
|
2 | let x: _ = "".chars().collect::<B>();
| +++++
Since they aren't sure what this B is doing, but they realize that that it is a type parameter, they decide "oh, Rust can infer types for me, I'll just let it infer it", and decide to add the turbofish with _, i.e., ::<_>, making the code into this (Playground link):
fn main() {
let x: _ = "".chars().collect::<_>();
}Again any seasoned Rust programmer would instantly recognize that this is unhelpful, but nonetheless, this leads to the following output:
error[E0282]: type annotations needed
--> src/main.rs:2:27
|
2 | let x: _ = "".chars().collect::<_>();
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect`
|
help: consider specifying the generic argument
|
2 | let x: _ = "".chars().collect::<_>();
| ~~~~~
At this point, we've reached a fixed-point, and the error message is copied over to chat-message-platform-of-choice, with an "excuse me what rust" message:

I help them understand what happened, and they fix the issue, and go on their way. However, this now seems like a point where diagnostics could be improved. (Btw, the original issue happened nested inside an iterator chain inside another iterator chain, and there was a type error along the way too, so lots more issues there; I've distilled it down to the above story just to remove all irrelevant details; also, while not in the above story, if instead of beginning with the : _, someone added the turbofish first (i.e., let x = "".chars().collect::<_>();), then too one hits the final fixed-point case)
What could be improved:
- If something is explicitly marked as "to be inferred" via the
_, maybe something like "cannot infer type of the type parameterB(here,_) declared on the associated functioncollect" or similar. Probably someone can come up with a better way to write that though, but there should be something that connects theB. - If both "sides" are marked to be inferred (in this case, type of
xand type parameter in the turbofish), and making any one of them explicit would be sufficient, having an error message that says this might help. - Adding a diagnostic that specifically points out such annotations in general would also potentially help. In particular, I don't see any situation where (verbatim)
::<_>is useful; except maybe in this animation. Having a diagnostic that tells users would probably be good. Similarly for (verbatim): _. (I hope what I am saying here makes sense: I'm saying, as an example,::<Vec<_>>is fine, but::<_>is not). - (Not 100% the goal of the above story, but still)
collectcould have a special diagnostic help message that mentions containers, rather than theBwhich can be confusing to new users.