-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Logically identical code. One compiles, one does not #116572
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
Comments
If we do this, I'd expect A workable solution would be instead to change the error message: the code that emits "this might have zero elements to iterate on" could check if the pattern is a single binding and emit a better error message if that's the case. I expect this is rather easy to do, so marking this as an easy issue. |
@rustbot claim |
You figured it out 👍 Open a topic on #t-compiler/help on Zulip when you have questions! |
Thank you for your kind attention! |
In the while let version, the compiler sees the while let result = f() statement and tries to match the result of f() to the pattern result. However, since f() returns a Result<T, E> which can be either Ok(T) or Err(E), the compiler is unsure how to match this result to the pattern result. This ambiguity leads to the error you encountered. On the other hand, in the loop version, the compiler doesn't have to match the result of f() to any pattern. It simply calls f() in each iteration and checks the result directly. This approach avoids the ambiguity and compiles successfully. |
@Nadrieril |
Yes, go ahead! |
@rustbot claim |
Minimization: fn foo() -> bool {
while let x = false {
if x { return true }
}
//~^ ERROR mismatched types
} Perhaps the compiler treats it similarly to this, which is what I would expect it might do: fn foo() -> bool {
loop {
let x = false else { break };
// ^^^^^
//~^ ERROR mismatched types
if x { return true }
}
} @rustbot labels +A-diagnostics @Kohei316: To confirm, you're planning to improve the diagnostics as described above, not try to change the behavior, yes? |
Yes.And thank you for your minimum code.It became clearer what to do. |
I tried to compile this code playground link:
However, it produces an error. If you uncomment the
unreachable!()
, it will work. Here's the error message:This code is functionally identical to the
while let
code and can compile without anunreachable!()
:The code in the while loop is irrefutable, so it is functionally the same as the
loop
case. Even if it's not a good practice to use an irrefutable statement in a while loop (and clippy will catch this) I think it should still compile.My main reason for wanting it to compile is that while iterating, I wrote the
while let
version first, and because I could not get it to compile without theunreachable!()
statement mistakenly believed that the compiler would not allow something like the second result. As a result of that mistaken impression ended up with this code:Which is not ideal (needs a temp mutable variable). A co-worker without the above learned helplessness
unreachable!()
experience wrote this code below, which I believe is a much better way to implement the logic as it does not require a temp mutable variable:So effectively, I'm advocating for
while let var = //...
to be treated the same asloop { let var = //...
, not because I think it's a good idea, but because having one error and not the other gives false feedback to the coder.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: