Skip to content

Commit 1f048a3

Browse files
authored
Unrolled build for rust-lang#115999
Rollup merge of rust-lang#115999 - matthewjasper:closure-capture-let-guards, r=b-naber Capture scrutinee of if let guards correctly Previously we were always capturing by value. cc rust-lang#51114
2 parents aadb571 + d4ffb3b commit 1f048a3

File tree

5 files changed

+164
-4
lines changed

5 files changed

+164
-4
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
664664
);
665665
self.walk_pat(discr_place, arm.pat, arm.guard.is_some());
666666

667-
if let Some(hir::Guard::If(e)) = arm.guard {
668-
self.consume_expr(e)
669-
} else if let Some(hir::Guard::IfLet(ref l)) = arm.guard {
670-
self.consume_expr(l.init)
667+
match arm.guard {
668+
Some(hir::Guard::If(ref e)) => self.consume_expr(e),
669+
Some(hir::Guard::IfLet(ref l)) => {
670+
self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow))
671+
}
672+
None => {}
671673
}
672674

673675
self.consume_expr(arm.body);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0505]: cannot move out of `value` because it is borrowed
2+
--> $DIR/if-let-guards-errors.rs:16:13
3+
|
4+
LL | let f = |x: &E| {
5+
| ------- borrow of `value` occurs here
6+
LL | match &x {
7+
LL | E::Number(_) if let E::Number(ref mut n) = *value => { }
8+
| ------ borrow occurs due to use in closure
9+
...
10+
LL | let x = value;
11+
| ^^^^^ move out of `value` occurs here
12+
LL |
13+
LL | drop(f);
14+
| - borrow later used here
15+
16+
error[E0382]: use of moved value: `value`
17+
--> $DIR/if-let-guards-errors.rs:28:13
18+
|
19+
LL | fn if_let_move(value: Box<E>) {
20+
| ----- move occurs because `value` has type `Box<E>`, which does not implement the `Copy` trait
21+
LL | let f = |x: &E| {
22+
| ------- value moved into closure here
23+
LL | match &x {
24+
LL | E::Number(_) if let E::String(s) = *value => { }
25+
| ------ variable moved due to use in closure
26+
...
27+
LL | let x = value;
28+
| ^^^^^ value used here after move
29+
30+
error: aborting due to 2 previous errors
31+
32+
Some errors have detailed explanations: E0382, E0505.
33+
For more information about an error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0505]: cannot move out of `value` because it is borrowed
2+
--> $DIR/if-let-guards-errors.rs:16:13
3+
|
4+
LL | let f = |x: &E| {
5+
| ------- borrow of `*value` occurs here
6+
LL | match &x {
7+
LL | E::Number(_) if let E::Number(ref mut n) = *value => { }
8+
| ------ borrow occurs due to use in closure
9+
...
10+
LL | let x = value;
11+
| ^^^^^ move out of `value` occurs here
12+
LL |
13+
LL | drop(f);
14+
| - borrow later used here
15+
16+
error[E0382]: use of moved value: `value`
17+
--> $DIR/if-let-guards-errors.rs:28:13
18+
|
19+
LL | fn if_let_move(value: Box<E>) {
20+
| ----- move occurs because `value` has type `Box<E>`, which does not implement the `Copy` trait
21+
LL | let f = |x: &E| {
22+
| ------- value moved into closure here
23+
LL | match &x {
24+
LL | E::Number(_) if let E::String(s) = *value => { }
25+
| ------ variable moved due to use in closure
26+
...
27+
LL | let x = value;
28+
| ^^^^^ value used here after move
29+
30+
error: aborting due to 2 previous errors
31+
32+
Some errors have detailed explanations: E0382, E0505.
33+
For more information about an error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Check the if let guards don't force capture by value
2+
// revisions: e2018 e2021
3+
//[e2018] edition:2018
4+
//[e2021] edition:2021
5+
6+
#![feature(if_let_guard)]
7+
#![allow(irrefutable_let_patterns)]
8+
9+
fn if_let_ref_mut(mut value: Box<E>) {
10+
let f = |x: &E| {
11+
match &x {
12+
E::Number(_) if let E::Number(ref mut n) = *value => { }
13+
_ => {}
14+
}
15+
};
16+
let x = value;
17+
//~^ ERROR cannot move out of `value` because it is borrowed
18+
drop(f);
19+
}
20+
21+
fn if_let_move(value: Box<E>) {
22+
let f = |x: &E| {
23+
match &x {
24+
E::Number(_) if let E::String(s) = *value => { }
25+
_ => {}
26+
}
27+
};
28+
let x = value;
29+
//~^ ERROR use of moved value: `value`
30+
}
31+
32+
enum E {
33+
String(String),
34+
Number(i32),
35+
}
36+
37+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Check the if let guards don't force capture by value
2+
// revisions: e2018 e2021
3+
// check-pass
4+
//[e2018] edition:2018
5+
//[e2021] edition:2021
6+
7+
#![feature(if_let_guard)]
8+
#![allow(irrefutable_let_patterns)]
9+
10+
fn if_let_underscore(value: Box<E>) {
11+
|x: &E| {
12+
match &x {
13+
E::Number(_) if let _ = *value => { }
14+
_ => {}
15+
}
16+
};
17+
let x = value;
18+
}
19+
20+
fn if_let_copy(value: Box<E>) {
21+
|x: &E| {
22+
match &x {
23+
E::Number(_) if let E::Number(n) = *value => { }
24+
_ => {}
25+
}
26+
};
27+
let x = value;
28+
}
29+
30+
fn if_let_ref(value: Box<E>) {
31+
|x: &E| {
32+
match &x {
33+
E::Number(_) if let E::Number(ref n) = *value => { }
34+
_ => {}
35+
}
36+
};
37+
let x = value;
38+
}
39+
40+
fn if_let_ref_mut(mut value: Box<E>) {
41+
|x: &E| {
42+
match &x {
43+
E::Number(_) if let E::Number(ref mut n) = *value => { }
44+
_ => {}
45+
}
46+
};
47+
let x = value;
48+
}
49+
50+
enum E {
51+
String(String),
52+
Number(i32),
53+
}
54+
55+
fn main() {}

0 commit comments

Comments
 (0)