Skip to content

Commit 6e94012

Browse files
authored
Rollup merge of #106005 - LeSeulArtichaut:if-let-guard-borrowck-test, r=Nilstrieb
Test the borrowck behavior of if-let guards Add some tests to make sure that if-let guards behave the same as if guards with respect to borrow-checking. Most of them are a naive adaptation, replacing an `if` guard with `if let Some(())`. This includes regression tests for notable issues that arose for if guards (#24535, #27282, #29723, #31287) as suggested in #51114 (comment). cc `@pnkfelix` are there any other tests that you would want to see? cc tracking issue #51114
2 parents da07053 + 56aaf74 commit 6e94012

27 files changed

+645
-62
lines changed

src/test/ui/borrowck/borrowck-drop-from-guard.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(if_let_guard)]
2+
13
fn foo(_:String) {}
24

35
fn main()
@@ -8,4 +10,11 @@ fn main()
810
Some(_) => {}
911
None => { foo(my_str); } //~ ERROR [E0382]
1012
}
13+
14+
let my_str = "hello".to_owned();
15+
match Some(42) {
16+
Some(_) if let Some(()) = { drop(my_str); None } => {}
17+
Some(_) => {}
18+
None => { foo(my_str); } //~ ERROR [E0382]
19+
}
1120
}

src/test/ui/borrowck/borrowck-drop-from-guard.stderr

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `my_str`
2-
--> $DIR/borrowck-drop-from-guard.rs:9:23
2+
--> $DIR/borrowck-drop-from-guard.rs:11:23
33
|
44
LL | let my_str = "hello".to_owned();
55
| ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
@@ -15,6 +15,23 @@ help: consider cloning the value if the performance cost is acceptable
1515
LL | Some(_) if { drop(my_str.clone()); false } => {}
1616
| ++++++++
1717

18-
error: aborting due to previous error
18+
error[E0382]: use of moved value: `my_str`
19+
--> $DIR/borrowck-drop-from-guard.rs:18:23
20+
|
21+
LL | let my_str = "hello".to_owned();
22+
| ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
23+
LL | match Some(42) {
24+
LL | Some(_) if let Some(()) = { drop(my_str); None } => {}
25+
| ------ value moved here
26+
LL | Some(_) => {}
27+
LL | None => { foo(my_str); }
28+
| ^^^^^^ value used here after move
29+
|
30+
help: consider cloning the value if the performance cost is acceptable
31+
|
32+
LL | Some(_) if let Some(()) = { drop(my_str.clone()); None } => {}
33+
| ++++++++
34+
35+
error: aborting due to 2 previous errors
1936

2037
For more information about this error, try `rustc --explain E0382`.

src/test/ui/borrowck/borrowck-mutate-in-guard.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#![feature(if_let_guard)]
2+
13
enum Enum<'a> {
24
A(&'a isize),
35
B(bool),
46
}
57

6-
fn foo() -> isize {
8+
fn if_guard() -> isize {
79
let mut n = 42;
810
let mut x = Enum::A(&mut n);
911
match x {
@@ -16,6 +18,17 @@ fn foo() -> isize {
1618
}
1719
}
1820

19-
fn main() {
20-
foo();
21+
fn if_let_guard() -> isize {
22+
let mut n = 42;
23+
let mut x = Enum::A(&mut n);
24+
match x {
25+
Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
26+
//~^ ERROR cannot assign `x` in match guard
27+
Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
28+
//~^ ERROR cannot mutably borrow `x` in match guard
29+
Enum::A(p) => *p,
30+
Enum::B(_) => 2,
31+
}
2132
}
33+
34+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
11
error[E0510]: cannot assign `x` in match guard
2-
--> $DIR/borrowck-mutate-in-guard.rs:10:25
2+
--> $DIR/borrowck-mutate-in-guard.rs:12:25
33
|
44
LL | match x {
55
| - value is immutable in match guard
66
LL | Enum::A(_) if { x = Enum::B(false); false } => 1,
77
| ^^^^^^^^^^^^^^^^^^ cannot assign
88

99
error[E0510]: cannot mutably borrow `x` in match guard
10-
--> $DIR/borrowck-mutate-in-guard.rs:12:33
10+
--> $DIR/borrowck-mutate-in-guard.rs:14:33
1111
|
1212
LL | match x {
1313
| - value is immutable in match guard
1414
...
1515
LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
1616
| ^^^^^^ cannot mutably borrow
1717

18-
error: aborting due to 2 previous errors
18+
error[E0510]: cannot assign `x` in match guard
19+
--> $DIR/borrowck-mutate-in-guard.rs:25:40
20+
|
21+
LL | match x {
22+
| - value is immutable in match guard
23+
LL | Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
24+
| ^^^^^^^^^^^^^^^^^^ cannot assign
25+
26+
error[E0510]: cannot mutably borrow `x` in match guard
27+
--> $DIR/borrowck-mutate-in-guard.rs:27:48
28+
|
29+
LL | match x {
30+
| - value is immutable in match guard
31+
...
32+
LL | Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
33+
| ^^^^^^ cannot mutably borrow
34+
35+
error: aborting due to 4 previous errors
1936

2037
For more information about this error, try `rustc --explain E0510`.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
#![feature(if_let_guard)]
2+
13
fn main() {
24
let a = Some("...".to_owned());
35
let b = match a {
46
Some(_) if { drop(a); false } => None,
57
x => x, //~ ERROR use of moved value: `a`
68
};
7-
println!("{:?}", b);
9+
10+
let a = Some("...".to_owned());
11+
let b = match a {
12+
Some(_) if let Some(()) = { drop(a); None } => None,
13+
x => x, //~ ERROR use of moved value: `a`
14+
};
815
}

src/test/ui/borrowck/issue-31287-drop-in-guard.stderr

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `a`
2-
--> $DIR/issue-31287-drop-in-guard.rs:5:9
2+
--> $DIR/issue-31287-drop-in-guard.rs:7:9
33
|
44
LL | let a = Some("...".to_owned());
55
| - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
@@ -14,6 +14,22 @@ help: consider cloning the value if the performance cost is acceptable
1414
LL | Some(_) if { drop(a.clone()); false } => None,
1515
| ++++++++
1616

17-
error: aborting due to previous error
17+
error[E0382]: use of moved value: `a`
18+
--> $DIR/issue-31287-drop-in-guard.rs:13:9
19+
|
20+
LL | let a = Some("...".to_owned());
21+
| - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
22+
LL | let b = match a {
23+
LL | Some(_) if let Some(()) = { drop(a); None } => None,
24+
| - value moved here
25+
LL | x => x,
26+
| ^ value used here after move
27+
|
28+
help: consider cloning the value if the performance cost is acceptable
29+
|
30+
LL | Some(_) if let Some(()) = { drop(a.clone()); None } => None,
31+
| ++++++++
32+
33+
error: aborting due to 2 previous errors
1834

1935
For more information about this error, try `rustc --explain E0382`.

src/test/ui/issues/issue-29723.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// test for https://github.com/rust-lang/rust/issues/29723
22

3+
#![feature(if_let_guard)]
4+
35
fn main() {
46
let s = String::new();
57
let _s = match 0 {
@@ -11,4 +13,10 @@ fn main() {
1113
//~^ ERROR use of moved value: `s`
1214
}
1315
};
16+
17+
let s = String::new();
18+
let _s = match 0 {
19+
0 if let Some(()) = { drop(s); None } => String::from("oops"),
20+
_ => s //~ ERROR use of moved value: `s`
21+
};
1422
}

src/test/ui/issues/issue-29723.stderr

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `s`
2-
--> $DIR/issue-29723.rs:10:13
2+
--> $DIR/issue-29723.rs:12:13
33
|
44
LL | let s = String::new();
55
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
@@ -15,6 +15,22 @@ help: consider cloning the value if the performance cost is acceptable
1515
LL | 0 if { drop(s.clone()); false } => String::from("oops"),
1616
| ++++++++
1717

18-
error: aborting due to previous error
18+
error[E0382]: use of moved value: `s`
19+
--> $DIR/issue-29723.rs:20:14
20+
|
21+
LL | let s = String::new();
22+
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
23+
LL | let _s = match 0 {
24+
LL | 0 if let Some(()) = { drop(s); None } => String::from("oops"),
25+
| - value moved here
26+
LL | _ => s
27+
| ^ value used here after move
28+
|
29+
help: consider cloning the value if the performance cost is acceptable
30+
|
31+
LL | 0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"),
32+
| ++++++++
33+
34+
error: aborting due to 2 previous errors
1935

2036
For more information about this error, try `rustc --explain E0382`.

src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// See further discussion on rust-lang/rust#24535,
66
// rust-lang/rfcs#1006, and rust-lang/rfcs#107
77

8+
#![feature(if_let_guard)]
9+
810
fn main() {
911
rust_issue_24535();
1012
rfcs_issue_1006_1();
@@ -23,6 +25,12 @@ fn rust_issue_24535() {
2325
3 if compare(&a, &mut 3) => (),
2426
_ => panic!("nope"),
2527
}
28+
29+
match a {
30+
0 => panic!("nope"),
31+
3 if let true = compare(&a, &mut 3) => (),
32+
_ => panic!("nope"),
33+
}
2634
}
2735

2836
fn rfcs_issue_1006_1() {

src/test/ui/nll/issue-27282-move-match-input-into-guard.rs

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
// reaches the panic code when executed, despite the compiler warning
88
// about that match arm being unreachable.
99

10+
#![feature(if_let_guard)]
11+
1012
fn main() {
1113
let b = &mut true;
1214
match b {
@@ -17,4 +19,16 @@ fn main() {
1719
&mut true => { println!("You might think we should get here"); },
1820
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
1921
}
22+
23+
let b = &mut true;
24+
match b {
25+
//~^ ERROR use of moved value: `b` [E0382]
26+
&mut false => {}
27+
_ if let Some(()) = {
28+
(|| { let bar = b; *bar = false; })();
29+
None
30+
} => {}
31+
&mut true => {}
32+
_ => {}
33+
}
2034
}

src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `b`
2-
--> $DIR/issue-27282-move-match-input-into-guard.rs:12:5
2+
--> $DIR/issue-27282-move-match-input-into-guard.rs:14:5
33
|
44
LL | let b = &mut true;
55
| - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
@@ -11,6 +11,19 @@ LL | _ if { (|| { let bar = b; *bar = false; })();
1111
| |
1212
| value moved into closure here
1313

14-
error: aborting due to previous error
14+
error[E0382]: use of moved value: `b`
15+
--> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
16+
|
17+
LL | let b = &mut true;
18+
| - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
19+
LL | match b {
20+
| ^^^^^^^ value used here after move
21+
...
22+
LL | (|| { let bar = b; *bar = false; })();
23+
| -- - variable moved due to use in closure
24+
| |
25+
| value moved into closure here
26+
27+
error: aborting due to 2 previous errors
1528

1629
For more information about this error, try `rustc --explain E0382`.

src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// mutable borrows in match guards by hiding the mutable borrow in a
33
// guard behind a move (of the ref mut pattern id) within a closure.
44

5+
#![feature(if_let_guard)]
6+
57
fn main() {
68
match Some(&4) {
79
None => {},
@@ -10,4 +12,12 @@ fn main() {
1012
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
1113
Some(s) => std::process::exit(*s),
1214
}
15+
16+
match Some(&4) {
17+
None => {},
18+
ref mut foo
19+
if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
20+
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
21+
Some(s) => std::process::exit(*s),
22+
}
1323
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0507]: cannot move out of `foo` in pattern guard
2-
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19
2+
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19
33
|
44
LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
55
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -8,6 +8,16 @@ LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
88
|
99
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
1010

11-
error: aborting due to previous error
11+
error[E0507]: cannot move out of `foo` in pattern guard
12+
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
13+
|
14+
LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
15+
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
16+
| |
17+
| move out of `foo` occurs here
18+
|
19+
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
20+
21+
error: aborting due to 2 previous errors
1222

1323
For more information about this error, try `rustc --explain E0507`.

src/test/ui/nll/issue-27282-mutation-in-guard.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(if_let_guard)]
2+
13
fn main() {
24
match Some(&4) {
35
None => {},
@@ -10,4 +12,15 @@ fn main() {
1012
Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
1113
_ => println!("Here is some supposedly unreachable code."),
1214
}
15+
16+
match Some(&4) {
17+
None => {},
18+
ref mut foo
19+
if let Some(()) = {
20+
(|| { let bar = foo; bar.take() })();
21+
//~^ ERROR cannot move out of `foo` in pattern guard
22+
None
23+
} => {},
24+
Some(_) => {},
25+
}
1326
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0507]: cannot move out of `foo` in pattern guard
2-
--> $DIR/issue-27282-mutation-in-guard.rs:6:18
2+
--> $DIR/issue-27282-mutation-in-guard.rs:8:18
33
|
44
LL | (|| { let bar = foo; bar.take() })();
55
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })();
88
|
99
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
1010

11-
error: aborting due to previous error
11+
error[E0507]: cannot move out of `foo` in pattern guard
12+
--> $DIR/issue-27282-mutation-in-guard.rs:20:18
13+
|
14+
LL | (|| { let bar = foo; bar.take() })();
15+
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
16+
| |
17+
| move out of `foo` occurs here
18+
|
19+
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
20+
21+
error: aborting due to 2 previous errors
1222

1323
For more information about this error, try `rustc --explain E0507`.

0 commit comments

Comments
 (0)