Skip to content

Improving type inference / annotation explicitness diagnostic #105510

Closed
@jaybosamiya

Description

@jaybosamiya

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:
screenshot of text stating 'excuse me what rust' where the 'rust' is highlighted as an alert

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:

  1. If something is explicitly marked as "to be inferred" via the _, maybe something like "cannot infer type of the type parameter B (here, _) declared on the associated function collect" or similar. Probably someone can come up with a better way to write that though, but there should be something that connects the B.
  2. If both "sides" are marked to be inferred (in this case, type of x and type parameter in the turbofish), and making any one of them explicit would be sufficient, having an error message that says this might help.
  3. 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).
  4. (Not 100% the goal of the above story, but still) collect could have a special diagnostic help message that mentions containers, rather than the B which can be confusing to new users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions