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

expected (), found usize, while really this is the other way around #51767

Closed
DutchGhost opened this issue Jun 24, 2018 · 4 comments · Fixed by #63337
Closed

expected (), found usize, while really this is the other way around #51767

DutchGhost opened this issue Jun 24, 2018 · 4 comments · Fixed by #63337
Labels
A-diagnostics Area: Messages for errors, warnings, and lints

Comments

@DutchGhost
Copy link
Contributor

DutchGhost commented Jun 24, 2018

When playing around in the playground, I found an error message that was kind of strange for the situation:

fn main() {
    [(); loop { break; } ]    
}

The error message is as follow:

  Compiling playground v0.0.1 (file:///playground)
error[E0308]: mismatched types
 --> src/main.rs:2:17
  |
2 |     [(); loop { break; } ]    
  |                 ^^^^^ expected (), found usize
  |
  = note: expected type `()`
             found type `usize`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

playground link: https://play.rust-lang.org/?gist=c6caaee68d6886fce7e3f0af324f5338&version=nightly&mode=debug
The error message would make more sense if described as Expected usize, found (), or just not permit loop {} constructs at all at the place of the length of an array.

@lukaslueg
Copy link
Contributor

lukaslueg commented Jun 25, 2018

The note on E0308 always bugs me, because it's either completely obvious or completely dubious what the compiler is trying to tell me. The problem is that both the "expected" and the "found" types are deduced by the compiler and the note does not provide a hint about why type X is expected and why type Y is actually used. If the error occurs in a situation with complex type relations, we always have to go back and rethink "OK, either the expected type is wrong or the found type is wrong. Which is it?" The error can appear where the meaning of the words "expected" and "found" is seemingly reversed because the programmer expected something different from what the compiler expected, adding to the confusion.

Sometimes we get more info, sometimes not:

fn foo() -> i32 {
    let s = "bar".chars().count();
    s
}

... clearly blames s as usize with "expected i32 because of return type". This is helpful.

fn foo() -> i32 {
    let s: i32 = "bar".chars().count();
    s
}

... blames the rhs with "expected i32, found usize". The compiler does not tell me why i32 is expected here. Although the compiler's "expectation" is MORE explicitly visible - the only step of reasoning is actually on the same line - the error message has actually degraded.

It would be very helpful if E0308 would always display at least one line of reasoning, even if trivial. In the example above, it would something to the tune of

* expected `i32`
   * because of assignment to `s`
   * `s` has explicit type `i32`
* found type `usize`
   * because `Iterator::count()` has return-type `usize`

A similar example to OP's code would be

#![feature(const_fn)]

const fn foo() -> i32 {
    1
}

fn main() {
    [(); { foo() } ];
}

The error is

7 | fn main() {
  |           - expected `()` because of default return type
8 |     [(); { foo() } ];
  |            ^^^^^ expected usize, found i32

Asides from the unrelated "expected () because of default return type" regarding main() (notice the semicolon): This error could be completely un-confusing if the compiler could state something to the tune of

* expected `usize`
  * because value of array-length must have type `usize`
* found `i32`
  * because `foo()` has return-type `i32`

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

CC #61065, #61066, #61067 for different parts of the previous comment

Centril added a commit to Centril/rust that referenced this issue Aug 9, 2019
Tweak mismatched types error

- Change expected/found for type mismatches in `break`
- Be more accurate when talking about diverging match arms
- Tweak wording of function without a return value
- Suggest calling bare functions when their return value can be coerced to the expected type
- Give more parsing errors when encountering `foo(_, _, _)`

Fix rust-lang#51767, fix rust-lang#62677, fix rust-lang#63136, cc rust-lang#37384, cc rust-lang#35241.
Centril added a commit to Centril/rust that referenced this issue Aug 9, 2019
Tweak mismatched types error

- Change expected/found for type mismatches in `break`
- Be more accurate when talking about diverging match arms
- Tweak wording of function without a return value
- Suggest calling bare functions when their return value can be coerced to the expected type
- Give more parsing errors when encountering `foo(_, _, _)`

Fix rust-lang#51767, fix rust-lang#62677, fix rust-lang#63136, cc rust-lang#37384, cc rust-lang#35241.
Centril added a commit to Centril/rust that referenced this issue Aug 9, 2019
Tweak mismatched types error

- Change expected/found for type mismatches in `break`
- Be more accurate when talking about diverging match arms
- Tweak wording of function without a return value
- Suggest calling bare functions when their return value can be coerced to the expected type
- Give more parsing errors when encountering `foo(_, _, _)`

Fix rust-lang#51767, fix rust-lang#62677, fix rust-lang#63136, cc rust-lang#37384, cc rust-lang#35241, cc rust-lang#51669.
Centril added a commit to Centril/rust that referenced this issue Aug 10, 2019
Tweak mismatched types error

- Change expected/found for type mismatches in `break`
- Be more accurate when talking about diverging match arms
- Tweak wording of function without a return value
- Suggest calling bare functions when their return value can be coerced to the expected type
- Give more parsing errors when encountering `foo(_, _, _)`

Fix rust-lang#51767, fix rust-lang#62677, fix rust-lang#63136, cc rust-lang#37384, cc rust-lang#35241, cc rust-lang#51669.
Centril added a commit to Centril/rust that referenced this issue Aug 10, 2019
Tweak mismatched types error

- Change expected/found for type mismatches in `break`
- Be more accurate when talking about diverging match arms
- Tweak wording of function without a return value
- Suggest calling bare functions when their return value can be coerced to the expected type
- Give more parsing errors when encountering `foo(_, _, _)`

Fix rust-lang#51767, fix rust-lang#62677, fix rust-lang#63136, cc rust-lang#37384, cc rust-lang#35241, cc rust-lang#51669.
@lukaslueg
Copy link
Contributor

May I suggest this issue is re-opened, even if it will stay open for a while. @estebank is doing the Lord's Work on compiler error messages and the recent changes are very welcome. Yet I think the fundamental problem of E0308 still remains: While E0308 reads as mismatched types, almost all of the times it actually means two lines of reasoning about these types lead to a contradiction, here are the contradicting results and here is why these two things must be true at the same time.

For the programmer, the whole point about the error is to figure out what went wrong in those lines of reasoning; the contradicting result (expected usize, found u32) is merely a hint what might have gone wrong and - most importantly - who is wrong: Is the expected type wrong, or is the found type wrong?

These are just my two cents, yet I may advertise to re-open this issue and maybe get the compiler's reasoning explained when E0308 hits, as in my aforementioned comment.

@estebank
Copy link
Contributor

@lukaslueg Thanks for the kind words.

I believe that this would fall under the umbrella of #61067: pointing at where the requirement is coming from. Sadly, the way we do type resolution currently means that we lose the chain of decisions that cause the current expected type to be expected. In order to improve diagnostics now (as opposed to wildly refactoring how type resolution is performed) we've been adding specific local analysis for local type errors (return type checking, for example). I believe that we can get 90% there with these kind of checks, like #61066 and #61067.

It is preferable to have more, smaller, targeted tickets that can be hyper focused and tackle-able by new contributors as opposed to large open ended tracking issues, particularly around diagnostics. Because of this I feel this ticket in particular could be closed. This, of course, unless I am missing some part of the original ticket that wasn't covered by #63337.

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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants