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

Add more detail to type inference error #61361

Merged
merged 6 commits into from
Jun 3, 2019
Merged

Conversation

estebank
Copy link
Contributor

@estebank estebank commented May 30, 2019

When encountering code where type inference fails, add more actionable
information:

fn main() {
    let foo = Vec::new();
}
error[E0282]: type annotations needed in `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
   |         |
   |         consider giving `foo` a type

Fix #25633.

@rust-highfive
Copy link
Collaborator

r? @varkor

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 30, 2019
@estebank
Copy link
Contributor Author

cc @rust-lang/wg-diagnostics

We still need to modify type printing to optionally accept a TypeVariableTable in order to properly print std::vec::Vec<T>.

I think that's an important thing to focus on in the short/medium term, together with using the local ident for external paths (std::vec::Vec -> Vec).

@estebank

This comment has been minimized.

Copy link
Contributor

@Centril Centril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not that sold on replacing _ but there seem to be bugs?

@estebank
Copy link
Contributor Author

@varkor would you prefer the following output?

error[E0282]: type annotations needed for `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T`
   |         |
   |         consider giving `foo` the type `std::vec::Vec<T>` with the type parameter `T` specified

We could also provide structured suggestions now that we have the type names, but I would like help to bikeshed the wording:

error[E0282]: type annotations needed for `T` in `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type
   |         |
   |         help: give `foo` a type with the type parameter `T` specified: `foo: std::vec::Vec<T>`

Also, I'm not sure we can verify with certainty that we're pointing at a let binding that doesn't have a type set, so I would prefer not to give a suggestion just yet.

For patterns I need to change the wording as it is subtly incorrect now.

estebank added 4 commits May 31, 2019 18:33
When encountering code where type inference fails, add more actionable
information:

```
fn main() {
    let foo = Vec::new();
}
```

```
error[E0282]: type annotations needed for `std::vec::Vec<_>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T`
   |         |
   |         consider giving `foo` the type `std::vec::Vec<_>` with the type parameter `T` specified
```

We still need to modify type printing to optionally accept a
`TypeVariableTable` in order to properly print `std::vec::Vec<T>`.

CC rust-lang#25633.
```
error[E0282]: type annotations needed in `std::result::Result<i32, E>`
 --> file7.rs:3:13
  |
3 |     let b = Ok(4);
  |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
  |         |
  |         consider giving `b` a type`
```
--> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
|
LL | let mut closure0 = None;
| ------------ consider giving `closure0` a type
| ------------ consider giving `closure0` the type `std::option::Option<T>` with the type parameter `_` specified
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a problem when the type parameters don't match up. (It'd be better for both to be _, as long as it's unambiguous.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe what is happening here is that _ and T are actually not unified, they are separate types as far as typeck is concerned. I'm not sure what the best way to go about it here would be :-/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheated a bit and changed it to be:

error[E0282]: type annotations needed for `std::option::Option<T>`
  --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
   |
LL |     let mut closure0 = None;
   |         ------------ consider giving `closure0` the explicit type `std::option::Option<T>`, with the type parameters specified
...
LL |                         return c();
   |                                ^^^ cannot infer type
   |
   = note: type must be known at this point

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's probably better.

@varkor
Copy link
Member

varkor commented Jun 1, 2019

I think a tweak to the message makes it slightly clearer (i.e. not to have users thinking: "but foo has a type already...").

error[E0282]: type annotations needed for `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T`
   |         |
   |         consider giving `foo` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified

Also, I'm not sure we can verify with certainty that we're pointing at a let binding that doesn't have a type set, so I would prefer not to give a suggestion just yet.

Structured suggestions would be nice, but only if we don't get it wrong, yeah.

@varkor
Copy link
Member

varkor commented Jun 3, 2019

Okay, I think this is good now! Thanks for being patient with all the back and forth about wording 😄

r=me if you're happy with the wording now too.

@varkor varkor added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 3, 2019
@estebank
Copy link
Contributor Author

estebank commented Jun 3, 2019

@bors r=varkor

Thanks for being patient with all the back and forth about wording

@varkor, we have high standards 😉

I'm just happy that the ty printing refactor made implementing this not only feasible, but rather straightforward, if hacky.

@bors
Copy link
Contributor

bors commented Jun 3, 2019

📌 Commit e420f44 has been approved by varkor

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 3, 2019
@bors
Copy link
Contributor

bors commented Jun 3, 2019

⌛ Testing commit e420f44 with merge d59dcb2...

bors added a commit that referenced this pull request Jun 3, 2019
Add more detail to type inference error

When encountering code where type inference fails, add more actionable
information:

```
fn main() {
    let foo = Vec::new();
}
```

```
error[E0282]: type annotations needed in `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
   |         |
   |         consider giving `foo` a type
```

Fix #25633.
@bors bors mentioned this pull request Jun 3, 2019
@bors
Copy link
Contributor

bors commented Jun 3, 2019

☀️ Test successful - checks-travis, status-appveyor
Approved by: varkor
Pushing d59dcb2 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jun 3, 2019
@bors bors merged commit e420f44 into rust-lang:master Jun 3, 2019
@@ -931,6 +945,8 @@ pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> {
binder_depth: usize,

pub region_highlight_mode: RegionHighlightMode,

pub name_resolver: Option<Box<&'a dyn Fn(ty::sty::TyVid) -> Option<String>>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please cc me on ty::print changes - but also, I have a few questions, such as "why is this a Box<&dyn Trait>?" - you can just remove the Box and everything would still work.

ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
ty::Infer(infer_ty) => {
if let ty::TyVar(ty_vid) = infer_ty {
if let Some(name) = self.infer_ty_name(ty_vid) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably override this in FmtPrinter's print_ty tbh, instead of adding infer_ty_name.

@@ -1206,6 +1223,10 @@ impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
}

impl<F: fmt::Write> PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
self.0.name_resolver.as_ref().and_then(|func| func(id))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a Deref impl, you don't need to write self.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incomplete error message: unable to infer enough type information about _
6 participants