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

Improving type mismatch errors #37384

Open
jonathandturner opened this Issue Oct 24, 2016 · 4 comments

Comments

Projects
None yet
6 participants
@jonathandturner
Copy link
Contributor

jonathandturner commented Oct 24, 2016

From: https://internals.rust-lang.org/t/improving-type-mismatch-errors/4263

Background

For a type mismatch error, there often are a known set of steps to transition from one type to another. If it's the first time the user has seen this error, they're forced to go read docs to find the correct API call to do the conversion. This takes time and can be a bit frustration. Luckily, over time your muscle memory will kick in with the known conversion (eg String->&str or &str->String) and it will then just be a minor inconvenience to do the fix.

Improved errors

The idea is pretty simple: have the compiler search the methods on the type looking for a compatible self parameter as the one argument and the expected type as the return type.

For the &str to String case, for example, it may find:

fn to_string(&self) -> String

This can then become a suggestion we give the user. Whereas currently we say:

error[E0308]: mismatched types
 --> <anon>:4:17
  |
4 |   expect_string("foo");
  |                 ^^^^^ expected struct `std::string::String`, found reference
  |
  = note: expected type `std::string::String`
  = note:    found type `&'static str`

We could potentially say:

error[E0308]: mismatched types
 --> <anon>:4:17
  |
4 |   expect_string("foo");
  |                 ^^^^^ expected struct `std::string::String`, found reference
  |
suggestion:
  |   expect_string("foo".to_string());
  |                      ------------ convert to a String

Caveats

Can't grab methods blindly

If we search for this pattern naively, we could potentially suggest methods that have side effects. While, yes, the correct type comes out, the dev could have inadvertently added a difficult to debug issue to their code in the process, just because the compiler told them to.

Also, some methods are very likely not what the user intended, like @GuillaumeGomez 's example:

now when you write "let x: usize = String::new();", it suggests capacity or len method

To prevent this, we may need to annotate methods with a "safe for suggestion" keyword that the suggestion logic can understand.

Multiple steps needed

Sometimes it's more than just one step. While we don't necessarily want to search deeply, we could do a limited number of steps. Assuming something like the "safe for suggestion" feature above, we're in a small, bounded search space and still able to deliver helpful suggestions.

Supporting & and &mut

Since adding an & or &mut is a common task in Rust, we should also add them to the search space for each step (assuming the type is allowed to take that step)

Multiple possibilities

Sometimes there are multiple possibilities for the conversion. It may be through one step (like .to_string() and .into()) or different ways to multi-step to the right type. We'd need to come up with a heuristic here, eg) possibly showing a couple suggestions sorted by the by the shortest in terms of character length.

How do generics/traits factor into this?

I have no idea :slight_smile: This may be easier than it seems, I'm not sure. If it proves to be tricky, maybe we can support them in a later revision of the idea as we get more experience with it?

@jonathandturner

This comment has been minimized.

Copy link
Contributor Author

jonathandturner commented Oct 24, 2016

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Oct 25, 2016

For the expected T, got &T case, check for a T: Clone impl

For the expected T, got &U case, it might be as simple as to check for a T: Borrow<U> impl and suggest to_owned().

for all other cases (or those without the appropriate impls), do the more fancy analysis with convert or arbitrary method search.

@GuillaumeGomez

This comment has been minimized.

Copy link
Member

GuillaumeGomez commented Oct 25, 2016

For people who might be interested by the status of my work on it: #37388

@GuillaumeGomez

This comment has been minimized.

Copy link
Member

GuillaumeGomez commented Oct 25, 2016

For the tag to use for safe suggestion, I propose:

#[safe_suggestion]
fn f() {}

// in case we have multiple suggestions
#[safe_suggestion="this function does this"]
fn f() {}

#[safe_suggestion="this other function does that"]
fn f2() {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.