Skip to content

Commit 2e959a7

Browse files
committed
Add tests
1 parent efcfb5a commit 2e959a7

File tree

4 files changed

+154
-56
lines changed

4 files changed

+154
-56
lines changed

tests/ui/nll/match-cfg-fake-edges.rs

+59-24
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,102 @@
33

44
#![feature(if_let_guard)]
55

6+
#[rustfmt::skip]
7+
fn all_patterns_are_tested() {
8+
// Even though `x` is never actually moved out of, we don't want borrowck results to be based on
9+
// whether MIR lowering reveals which patterns are unreachable.
10+
let x = String::new();
11+
let _ = match true {
12+
_ => {},
13+
_ => drop(x),
14+
};
15+
// Borrowck must not know the second arm is never run.
16+
drop(x); //~ ERROR use of moved value
17+
18+
let x = (String::new(), String::new());
19+
match x {
20+
(y, _) | (_, y) => (),
21+
}
22+
&x.0; //~ ERROR borrow of moved value
23+
// Borrowck must not know the second pattern never matches.
24+
&x.1; //~ ERROR borrow of moved value
25+
}
26+
27+
#[rustfmt::skip]
628
fn guard_always_precedes_arm(y: i32) {
7-
let mut x;
829
// x should always be initialized, as the only way to reach the arm is
930
// through the guard.
31+
let mut x;
1032
match y {
1133
0 | 2 if { x = 2; true } => x,
1234
_ => 2,
1335
};
1436

37+
let mut x;
38+
match y {
39+
_ => 2,
40+
0 | 2 if { x = 2; true } => x,
41+
};
42+
1543
let mut x;
1644
match y {
1745
0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
1846
_ => 2,
1947
};
2048
}
2149

50+
#[rustfmt::skip]
2251
fn guard_may_be_skipped(y: i32) {
52+
// Even though x *is* always initialized, we don't want to have borrowck results be based on
53+
// whether MIR lowering reveals which patterns are exhaustive.
54+
let x;
55+
match y {
56+
_ if { x = 2; true } => {},
57+
// Borrowck must not know the guard is always run.
58+
_ => drop(x), //~ ERROR used binding `x` is possibly-uninitialized
59+
};
60+
2361
let x;
24-
// Even though x *is* always initialized, we don't want to have borrowck
25-
// results be based on whether patterns are exhaustive.
2662
match y {
2763
_ if { x = 2; true } => 1,
28-
_ if {
29-
x; //~ ERROR E0381
30-
false
31-
} => 2,
64+
// Borrowck must not know the guard is always run.
65+
_ if { x; false } => 2, //~ ERROR used binding `x` isn't initialized
3266
_ => 3,
3367
};
3468

3569
let x;
3670
match y {
3771
_ if let Some(()) = { x = 2; Some(()) } => 1,
38-
_ if let Some(()) = {
39-
x; //~ ERROR E0381
40-
None
41-
} => 2,
72+
_ if let Some(()) = { x; None } => 2, //~ ERROR used binding `x` isn't initialized
4273
_ => 3,
4374
};
4475
}
4576

77+
#[rustfmt::skip]
4678
fn guard_may_be_taken(y: bool) {
47-
let x = String::new();
4879
// Even though x *is* never moved before the use, we don't want to have
4980
// borrowck results be based on whether patterns are disjoint.
81+
let x = String::new();
82+
match y {
83+
false if { drop(x); true } => {},
84+
// Borrowck must not know the guard is not run in the `true` case.
85+
true => drop(x), //~ ERROR use of moved value: `x`
86+
false => {},
87+
};
88+
89+
// Fine in the other order.
90+
let x = String::new();
5091
match y {
51-
false if { drop(x); true } => 1,
52-
true => {
53-
x; //~ ERROR use of moved value: `x`
54-
2
55-
}
56-
false => 3,
92+
true => drop(x),
93+
false if { drop(x); true } => {},
94+
false => {},
5795
};
5896

5997
let x = String::new();
6098
match y {
61-
false if let Some(()) = { drop(x); Some(()) } => 1,
62-
true => {
63-
x; //~ ERROR use of moved value: `x`
64-
2
65-
}
66-
false => 3,
99+
false if let Some(()) = { drop(x); Some(()) } => {},
100+
true => drop(x), //~ ERROR use of moved value: `x`
101+
false => {},
67102
};
68103
}
69104

+79-23
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,128 @@
1-
error[E0381]: used binding `x` isn't initialized
2-
--> $DIR/match-cfg-fake-edges.rs:29:13
1+
error[E0382]: use of moved value: `x`
2+
--> $DIR/match-cfg-fake-edges.rs:16:10
3+
|
4+
LL | let x = String::new();
5+
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
6+
...
7+
LL | _ => drop(x),
8+
| - value moved here
9+
...
10+
LL | drop(x);
11+
| ^ value used here after move
12+
|
13+
help: consider cloning the value if the performance cost is acceptable
14+
|
15+
LL | _ => drop(x.clone()),
16+
| ++++++++
17+
18+
error[E0382]: borrow of moved value: `x.0`
19+
--> $DIR/match-cfg-fake-edges.rs:22:5
20+
|
21+
LL | (y, _) | (_, y) => (),
22+
| - value moved here
23+
LL | }
24+
LL | &x.0;
25+
| ^^^^ value borrowed here after move
26+
|
27+
= note: move occurs because `x.0` has type `String`, which does not implement the `Copy` trait
28+
help: borrow this binding in the pattern to avoid moving the value
29+
|
30+
LL | (ref y, _) | (_, y) => (),
31+
| +++
32+
33+
error[E0382]: borrow of moved value: `x.1`
34+
--> $DIR/match-cfg-fake-edges.rs:24:5
35+
|
36+
LL | (y, _) | (_, y) => (),
37+
| - value moved here
38+
...
39+
LL | &x.1;
40+
| ^^^^ value borrowed here after move
41+
|
42+
= note: move occurs because `x.1` has type `String`, which does not implement the `Copy` trait
43+
help: borrow this binding in the pattern to avoid moving the value
44+
|
45+
LL | (y, _) | (_, ref y) => (),
46+
| +++
47+
48+
error[E0381]: used binding `x` is possibly-uninitialized
49+
--> $DIR/match-cfg-fake-edges.rs:58:19
350
|
451
LL | let x;
552
| - binding declared here but left uninitialized
653
...
54+
LL | _ => drop(x),
55+
| - ^ `x` used here but it is possibly-uninitialized
56+
| |
57+
| if this pattern is matched, `x` is not initialized
58+
59+
error[E0381]: used binding `x` isn't initialized
60+
--> $DIR/match-cfg-fake-edges.rs:65:16
61+
|
62+
LL | let x;
63+
| - binding declared here but left uninitialized
64+
LL | match y {
765
LL | _ if { x = 2; true } => 1,
866
| ----- binding initialized here in some conditions
9-
LL | _ if {
10-
LL | x;
11-
| ^ `x` used here but it isn't initialized
67+
LL | // Borrowck must not know the guard is always run.
68+
LL | _ if { x; false } => 2,
69+
| ^ `x` used here but it isn't initialized
1270
|
1371
help: consider assigning a value
1472
|
1573
LL | let x = 0;
1674
| +++
1775

1876
error[E0381]: used binding `x` isn't initialized
19-
--> $DIR/match-cfg-fake-edges.rs:39:13
77+
--> $DIR/match-cfg-fake-edges.rs:72:31
2078
|
2179
LL | let x;
2280
| - binding declared here but left uninitialized
2381
LL | match y {
2482
LL | _ if let Some(()) = { x = 2; Some(()) } => 1,
2583
| ----- binding initialized here in some conditions
26-
LL | _ if let Some(()) = {
27-
LL | x;
28-
| ^ `x` used here but it isn't initialized
84+
LL | _ if let Some(()) = { x; None } => 2,
85+
| ^ `x` used here but it isn't initialized
2986
|
3087
help: consider assigning a value
3188
|
3289
LL | let x = 0;
3390
| +++
3491

3592
error[E0382]: use of moved value: `x`
36-
--> $DIR/match-cfg-fake-edges.rs:53:13
93+
--> $DIR/match-cfg-fake-edges.rs:85:22
3794
|
3895
LL | let x = String::new();
3996
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
40-
...
41-
LL | false if { drop(x); true } => 1,
97+
LL | match y {
98+
LL | false if { drop(x); true } => {},
4299
| - value moved here
43-
LL | true => {
44-
LL | x;
45-
| ^ value used here after move
100+
LL | // Borrowck must not know the guard is not run in the `true` case.
101+
LL | true => drop(x),
102+
| ^ value used here after move
46103
|
47104
help: consider cloning the value if the performance cost is acceptable
48105
|
49-
LL | false if { drop(x.clone()); true } => 1,
106+
LL | false if { drop(x.clone()); true } => {},
50107
| ++++++++
51108

52109
error[E0382]: use of moved value: `x`
53-
--> $DIR/match-cfg-fake-edges.rs:63:13
110+
--> $DIR/match-cfg-fake-edges.rs:100:22
54111
|
55112
LL | let x = String::new();
56113
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
57114
LL | match y {
58-
LL | false if let Some(()) = { drop(x); Some(()) } => 1,
115+
LL | false if let Some(()) = { drop(x); Some(()) } => {},
59116
| - value moved here
60-
LL | true => {
61-
LL | x;
62-
| ^ value used here after move
117+
LL | true => drop(x),
118+
| ^ value used here after move
63119
|
64120
help: consider cloning the value if the performance cost is acceptable
65121
|
66-
LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1,
122+
LL | false if let Some(()) = { drop(x.clone()); Some(()) } => {},
67123
| ++++++++
68124

69-
error: aborting due to 4 previous errors
125+
error: aborting due to 8 previous errors
70126

71127
Some errors have detailed explanations: E0381, E0382.
72128
For more information about an error, try `rustc --explain E0381`.

tests/ui/nll/match-cfg-fake-edges2.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
55
let r = &mut y.1;
66
// We don't actually test y.1 to select the second arm, but we don't want
77
// borrowck results to be based on the order we match patterns.
8-
match y { //~ ERROR cannot use `y.1` because it was mutably borrowed
9-
(false, true) => 1,
10-
(true, _) => {
11-
r;
12-
2
13-
}
14-
(false, _) => 3,
8+
match y {
9+
//~^ ERROR cannot use `y.1` because it was mutably borrowed
10+
(false, true) => {}
11+
// Borrowck must not know we don't test `y.1` when `y.0` is `true`.
12+
(true, _) => drop(r),
13+
(false, _) => {}
14+
};
15+
16+
// Fine in the other order.
17+
let r = &mut y.1;
18+
match y {
19+
(true, _) => drop(r),
20+
(false, true) => {}
21+
(false, _) => {}
1522
};
1623
}
1724

tests/ui/nll/match-cfg-fake-edges2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ LL | let r = &mut y.1;
77
LL | match y {
88
| ^^^^^^^ use of borrowed `y.1`
99
...
10-
LL | r;
11-
| - borrow later used here
10+
LL | (true, _) => drop(r),
11+
| - borrow later used here
1212

1313
error: aborting due to 1 previous error
1414

0 commit comments

Comments
 (0)