-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
ICE on if let Some() = ...
expression in loop with variable shadowing and missing let keyword
#77218
Comments
Regressed in #75931 |
Cc @estebank |
Related: this code should probably have a suggestion for fn foo() {
let list = vec![Some(1), None, Some(3)];
for reference in list {
if /*let*/ Some(reference) = reference {
unimplemented!()
}
}
} Currently it produces:
|
Minimized (playground): // Type aliases to replace complex data types used in the original code.
pub type Data = usize;
pub type Key = usize;
pub type DataRef<'c> = &'c Data;
pub struct Cache<'c> {
cached_data_refs: Vec<DataRef<'c>>,
}
impl Cache<'_> {
pub fn data_ref_list(&mut self, key: &Key) {
for reference in vec![1, 2, 3] {
// Following `if` statement is the reason for compiler crash. To trigger the crash it
// is required to:
//
// * have `let` keyword missing from `if let Some(...)` expression
// * have binding name in the `Some(...)` portion of the `if let Some()` shadow the
// name from the outer loop
//
if /*let*/ Some(reference) = self.cached_data_refs.get(*key) {
unimplemented!()
}
}
}
} I think this might be caused by the lifetimes. |
Never mind! This causes it too, with no lifetimes (playground): pub struct Cache {
data: Vec<i32>,
}
impl Cache {
pub fn list_data(&mut self, key: &usize) {
for reference in vec![1, 2, 3] {
if /*let*/ Some(reference) = self.data.get(*key) {
unimplemented!()
}
}
}
} EDIT: removed the type aliases EDIT 2: changed EDIT 3: shortened names, removed comment |
Assigning |
Further minimized to this (playground): pub struct Cache {
data: Vec<i32>,
}
pub fn list_data(cache: &Cache, key: usize) {
for reference in vec![1, 2, 3] {
if /*let*/ Some(reference) = cache.data.get(key) {
unimplemented!()
}
}
} Having |
#75931 causes the operands to be typechecked twice: rust/compiler/rustc_typeck/src/check/expr.rs Lines 774 to 775 in d824b23
rust/compiler/rustc_typeck/src/check/expr.rs Lines 801 to 803 in d824b23
I think this has side effects that are causing problems by being applied twice. Commenting out the second 27 error[E0308]: mismatched types
- --> $DIR/if-let-typo.rs:6:12
- |
- LL | if 3 = foo {}
- | ^^^ expected integer, found enum `Option`
- |
- = note: expected type `{integer}`
- found enum `Option<{integer}>`
-
- error[E0308]: mismatched types (It still emits this error:)
|
@SNCPlay42 I tried a couple of things but it seems to me that you hit the nail in the head and we just need to remove the
@camelid this is caused because one side is seen to be |
I think I just found a smaller example (granted, it's not valid code any more, but how is one supposed to know that in case of ICE? ;-) ): fn main() {
let value = [7u8];
while Some(0) = value.get(0) {
}
} (If that's not the same error I'm happy to open a new ICE issue, but to me it looks the same, with all the |
…crum Tweak `if let` suggestion to be more liberal with suggestion and to not ICE Fix rust-lang#77218. Fix rust-lang#77238.
…crum Tweak `if let` suggestion to be more liberal with suggestion and to not ICE Fix rust-lang#77218. Fix rust-lang#77238.
Tweak `if let` suggestion to be more liberal with suggestion and to not ICE Fix rust-lang#77218. Fix rust-lang#77238.
Code
Meta
rustc --version --verbose
:Error output
Backtrace
The text was updated successfully, but these errors were encountered: