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

Type mismatch when pattern matching to a unit struct could really use some better diagnostics #48062

Closed
sgrif opened this issue Feb 8, 2018 · 2 comments · Fixed by #67741
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-feature-request Category: A feature request, i.e: not implemented / a PR. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@sgrif
Copy link
Contributor

sgrif commented Feb 8, 2018

I've answered a question like this every day for the past 3 days... https://users.rust-lang.org/t/how-to-create-a-new-option-serde-json-value-value/15466

The problem is with code like this:

struct foo;

let foo = 1;

Typically the let binding and the struct definition are much more separated, and the struct definition comes from a glob import. The error received is:

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 |     let foo = 1;
  |         ^^^ expected integral variable, found struct `main::foo`
  |
  = note: expected type `{integer}`
             found type `main::foo`

This error isn't wrong, and I'm not even proposing that we remove it. However, in the specific case where the match is on a unit struct, I do think it would be incredibly helpful to add a help diagnostic pointing at the span where foo was brought into scope, stating that a struct with zero fields named foo was imported. E.g.

 --> src/main.rs:2:4
  |
2 |     struct foo;
  |     ^^^^^^^^^^ note: A struct named `foo` with zero fields was brought into scope here.
  |

I have purposely biased this error message towards use vs definition, because I think the overwhelmingly common case is going to be from use not definition (though the error is still reasonable when pointing at the definition).

I'd be happy to implement this if it'd be accepted, though I think I'll probably need a bit of help.

@sgrif
Copy link
Contributor Author

sgrif commented Feb 8, 2018

Also am I the only one who thinks that type mismatch error is completely backwards? It really should be:

error[E0308]: mismatched types
 --> src/main.rs:4:11
  |
4 |     let foo = 1;
  |               ^ expected struct `main::foo`, found integral variable
  |
  = note: expected type `main::foo`
             found type `{integer}`

@estebank estebank added the A-diagnostics Area: Messages for errors, warnings, and lints label Feb 8, 2018
@oli-obk
Copy link
Contributor

oli-obk commented Feb 8, 2018

well... the binding initialization comes after computing the value to initialize with, so I think the order is correct.

Maybe it should be

error[E0308]: mismatched types
 --> src/main.rs:4:11
  |
4 |     let foo = 1;
  |         ^^^   ^ expected integral variable
  |         - found struct `main::foo`

@estebank estebank added C-feature-request Category: A feature request, i.e: not implemented / a PR. WG-diagnostics Working group: Diagnostics labels Mar 19, 2018
@estebank estebank added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-papercut Diagnostics: An error or lint that needs small tweaks. labels Oct 18, 2019
@estebank estebank added the D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. label Oct 30, 2019
Centril added a commit to Centril/rust that referenced this issue Mar 7, 2020
When encountering an Item in a pat context, point at the item def

```
error[E0308]: mismatched types
  --> $DIR/const-in-struct-pat.rs:8:17
   |
LL | struct foo;
   | ----------- `foo` defined here
...
LL |     let Thing { foo } = t;
   |                 ^^^ expected struct `std::string::String`, found struct `foo`
   |
   = note: `foo` is interpreted as a unit struct, not a new binding
help: you can bind the struct field to a different name
   |
LL |     let Thing { foo: other_foo } = t;
   |                 ^^^^^^^^^^^^^^
```
```
error[E0308]: mismatched types
  --> $DIR/const.rs:14:9
   |
LL | const FOO: Foo = Foo{bar: 5};
   | ----------------------------- constant defined here
...
LL |         FOO => {},
   |         ^^^
   |         |
   |         expected `&Foo`, found struct `Foo`
   |         `FOO` is interpreted as a constant, not a new binding
   |         help: use different name to introduce a new binding: `other_foo`
```

Fix rust-lang#55631, fix rust-lang#48062, cc rust-lang#42876.
@bors bors closed this as completed in e8bb6c0 Mar 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-feature-request Category: A feature request, i.e: not implemented / a PR. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants