Capture scrutinee of if let guards correctly
Previously we were always capturing by value.
This commit is contained in:
parent
62d9034a0d
commit
d4ffb3b08a
@ -664,10 +664,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
);
|
||||
self.walk_pat(discr_place, arm.pat, arm.guard.is_some());
|
||||
|
||||
if let Some(hir::Guard::If(e)) = arm.guard {
|
||||
self.consume_expr(e)
|
||||
} else if let Some(hir::Guard::IfLet(ref l)) = arm.guard {
|
||||
self.consume_expr(l.init)
|
||||
match arm.guard {
|
||||
Some(hir::Guard::If(ref e)) => self.consume_expr(e),
|
||||
Some(hir::Guard::IfLet(ref l)) => {
|
||||
self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow))
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.consume_expr(arm.body);
|
||||
|
@ -0,0 +1,33 @@
|
||||
error[E0505]: cannot move out of `value` because it is borrowed
|
||||
--> $DIR/if-let-guards-errors.rs:16:13
|
||||
|
|
||||
LL | let f = |x: &E| {
|
||||
| ------- borrow of `value` occurs here
|
||||
LL | match &x {
|
||||
LL | E::Number(_) if let E::Number(ref mut n) = *value => { }
|
||||
| ------ borrow occurs due to use in closure
|
||||
...
|
||||
LL | let x = value;
|
||||
| ^^^^^ move out of `value` occurs here
|
||||
LL |
|
||||
LL | drop(f);
|
||||
| - borrow later used here
|
||||
|
||||
error[E0382]: use of moved value: `value`
|
||||
--> $DIR/if-let-guards-errors.rs:28:13
|
||||
|
|
||||
LL | fn if_let_move(value: Box<E>) {
|
||||
| ----- move occurs because `value` has type `Box<E>`, which does not implement the `Copy` trait
|
||||
LL | let f = |x: &E| {
|
||||
| ------- value moved into closure here
|
||||
LL | match &x {
|
||||
LL | E::Number(_) if let E::String(s) = *value => { }
|
||||
| ------ variable moved due to use in closure
|
||||
...
|
||||
LL | let x = value;
|
||||
| ^^^^^ value used here after move
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0505.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
@ -0,0 +1,33 @@
|
||||
error[E0505]: cannot move out of `value` because it is borrowed
|
||||
--> $DIR/if-let-guards-errors.rs:16:13
|
||||
|
|
||||
LL | let f = |x: &E| {
|
||||
| ------- borrow of `*value` occurs here
|
||||
LL | match &x {
|
||||
LL | E::Number(_) if let E::Number(ref mut n) = *value => { }
|
||||
| ------ borrow occurs due to use in closure
|
||||
...
|
||||
LL | let x = value;
|
||||
| ^^^^^ move out of `value` occurs here
|
||||
LL |
|
||||
LL | drop(f);
|
||||
| - borrow later used here
|
||||
|
||||
error[E0382]: use of moved value: `value`
|
||||
--> $DIR/if-let-guards-errors.rs:28:13
|
||||
|
|
||||
LL | fn if_let_move(value: Box<E>) {
|
||||
| ----- move occurs because `value` has type `Box<E>`, which does not implement the `Copy` trait
|
||||
LL | let f = |x: &E| {
|
||||
| ------- value moved into closure here
|
||||
LL | match &x {
|
||||
LL | E::Number(_) if let E::String(s) = *value => { }
|
||||
| ------ variable moved due to use in closure
|
||||
...
|
||||
LL | let x = value;
|
||||
| ^^^^^ value used here after move
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0505.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
@ -0,0 +1,37 @@
|
||||
// Check the if let guards don't force capture by value
|
||||
// revisions: e2018 e2021
|
||||
//[e2018] edition:2018
|
||||
//[e2021] edition:2021
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(irrefutable_let_patterns)]
|
||||
|
||||
fn if_let_ref_mut(mut value: Box<E>) {
|
||||
let f = |x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let E::Number(ref mut n) = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
//~^ ERROR cannot move out of `value` because it is borrowed
|
||||
drop(f);
|
||||
}
|
||||
|
||||
fn if_let_move(value: Box<E>) {
|
||||
let f = |x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let E::String(s) = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
//~^ ERROR use of moved value: `value`
|
||||
}
|
||||
|
||||
enum E {
|
||||
String(String),
|
||||
Number(i32),
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,55 @@
|
||||
// Check the if let guards don't force capture by value
|
||||
// revisions: e2018 e2021
|
||||
// check-pass
|
||||
//[e2018] edition:2018
|
||||
//[e2021] edition:2021
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(irrefutable_let_patterns)]
|
||||
|
||||
fn if_let_underscore(value: Box<E>) {
|
||||
|x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let _ = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
}
|
||||
|
||||
fn if_let_copy(value: Box<E>) {
|
||||
|x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let E::Number(n) = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
}
|
||||
|
||||
fn if_let_ref(value: Box<E>) {
|
||||
|x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let E::Number(ref n) = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
}
|
||||
|
||||
fn if_let_ref_mut(mut value: Box<E>) {
|
||||
|x: &E| {
|
||||
match &x {
|
||||
E::Number(_) if let E::Number(ref mut n) = *value => { }
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
let x = value;
|
||||
}
|
||||
|
||||
enum E {
|
||||
String(String),
|
||||
Number(i32),
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user