Skip to content

Commit 232d661

Browse files
committed
Add more tests for or-patterns
1 parent 0687055 commit 232d661

8 files changed

+404
-0
lines changed

src/test/mir-opt/exponential-or.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Test that simple or-patterns don't get expanded to exponentially large CFGs
2+
3+
// ignore-tidy-linelength
4+
5+
#![feature(or_patterns)]
6+
7+
fn match_tuple(x: (u32, bool, Option<i32>, u32)) -> u32 {
8+
match x {
9+
(y @ (1 | 4), true | false, Some(1 | 8) | None, z @ (6..=9 | 13..=16)) => y + 2 * z,
10+
_ => 0,
11+
}
12+
}
13+
14+
fn main() {}
15+
16+
// END RUST SOURCE
17+
18+
// START rustc.match_tuple.SimplifyCfg-initial.after.mir
19+
// scope 1 {
20+
// debug y => _7;
21+
// debug z => _8;
22+
// }
23+
// bb0: {
24+
// FakeRead(ForMatchedPlace, _1);
25+
// switchInt((_1.0: u32)) -> [1u32: bb2, 4u32: bb2, otherwise: bb1];
26+
// }
27+
// bb1: {
28+
// _0 = const 0u32;
29+
// goto -> bb10;
30+
// }
31+
// bb2: {
32+
// _2 = discriminant((_1.2: std::option::Option<i32>));
33+
// switchInt(move _2) -> [0isize: bb4, 1isize: bb3, otherwise: bb1];
34+
// }
35+
// bb3: {
36+
// switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1i32: bb4, 8i32: bb4, otherwise: bb1];
37+
// }
38+
// bb4: {
39+
// _5 = Le(const 6u32, (_1.3: u32));
40+
// switchInt(move _5) -> [false: bb6, otherwise: bb5];
41+
// }
42+
// bb5: {
43+
// _6 = Le((_1.3: u32), const 9u32);
44+
// switchInt(move _6) -> [false: bb6, otherwise: bb8];
45+
// }
46+
// bb6: {
47+
// _3 = Le(const 13u32, (_1.3: u32));
48+
// switchInt(move _3) -> [false: bb1, otherwise: bb7];
49+
// }
50+
// bb7: {
51+
// _4 = Le((_1.3: u32), const 16u32);
52+
// switchInt(move _4) -> [false: bb1, otherwise: bb8];
53+
// }
54+
// bb8: {
55+
// falseEdges -> [real: bb9, imaginary: bb1];
56+
// }
57+
// bb9: {
58+
// StorageLive(_7);
59+
// _7 = (_1.0: u32);
60+
// StorageLive(_8);
61+
// _8 = (_1.3: u32);
62+
// StorageLive(_9);
63+
// _9 = _7;
64+
// StorageLive(_10);
65+
// StorageLive(_11);
66+
// _11 = _8;
67+
// _10 = Mul(const 2u32, move _11);
68+
// StorageDead(_11);
69+
// _0 = Add(move _9, move _10);
70+
// StorageDead(_10);
71+
// StorageDead(_9);
72+
// StorageDead(_8);
73+
// StorageDead(_7);
74+
// goto -> bb10;
75+
// }
76+
// bb10: {
77+
// return;
78+
// }
79+
// END rustc.match_tuple.SimplifyCfg-initial.after.mir

src/test/ui/borrowck/or-patterns.rs

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Test that borrow check considers all choices in an or pattern, even the
2+
// unreachable ones.
3+
4+
#![feature(or_patterns)]
5+
6+
fn or_pattern_moves_all(x: ((String, String),)) {
7+
match x {
8+
((y, _) | (_, y),) => (),
9+
}
10+
&x.0 .0;
11+
//~^ ERROR borrow of moved value
12+
&x.0 .1;
13+
//~^ ERROR borrow of moved value
14+
}
15+
16+
fn or_pattern_borrows_all(mut x: ((String, String),)) {
17+
let r = match x {
18+
((ref y, _) | (_, ref y),) => y,
19+
};
20+
&mut x.0 .0;
21+
//~^ ERROR cannot borrow
22+
&mut x.0 .1;
23+
//~^ ERROR cannot borrow
24+
drop(r);
25+
}
26+
27+
fn or_pattern_borrows_all_mut(mut x: ((String, String),)) {
28+
let r = match x {
29+
((ref mut y, _) | (_, ref mut y),) => y,
30+
};
31+
&x.0 .0;
32+
//~^ ERROR cannot borrow
33+
&x.0 .1;
34+
//~^ ERROR cannot borrow
35+
drop(r);
36+
}
37+
38+
fn let_or_pattern_moves_all(x: ((String, String),)) {
39+
let ((y, _) | (_, y),) = x;
40+
&x.0 .0;
41+
//~^ ERROR borrow of moved value
42+
&x.0 .1;
43+
//~^ ERROR borrow of moved value
44+
}
45+
46+
fn let_or_pattern_borrows_all(mut x: ((String, String),)) {
47+
let ((ref r, _) | (_, ref r),) = x;
48+
&mut x.0 .0;
49+
//~^ ERROR cannot borrow
50+
&mut x.0 .1;
51+
//~^ ERROR cannot borrow
52+
drop(r);
53+
}
54+
55+
fn let_or_pattern_borrows_all_mut(mut x: ((String, String),)) {
56+
let ((ref mut r, _) | (_, ref mut r),) = x;
57+
&x.0 .0;
58+
//~^ ERROR cannot borrow
59+
&x.0 .1;
60+
//~^ ERROR cannot borrow
61+
drop(r);
62+
}
63+
64+
fn main() {}
+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
error[E0382]: borrow of moved value: `x.0.0`
2+
--> $DIR/or-patterns.rs:10:5
3+
|
4+
LL | ((y, _) | (_, y),) => (),
5+
| - value moved here
6+
LL | }
7+
LL | &x.0 .0;
8+
| ^^^^^^^ value borrowed here after move
9+
|
10+
= note: move occurs because `x.0.0` has type `std::string::String`, which does not implement the `Copy` trait
11+
12+
error[E0382]: borrow of moved value: `x.0.1`
13+
--> $DIR/or-patterns.rs:12:5
14+
|
15+
LL | ((y, _) | (_, y),) => (),
16+
| - value moved here
17+
...
18+
LL | &x.0 .1;
19+
| ^^^^^^^ value borrowed here after move
20+
|
21+
= note: move occurs because `x.0.1` has type `std::string::String`, which does not implement the `Copy` trait
22+
23+
error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
24+
--> $DIR/or-patterns.rs:20:5
25+
|
26+
LL | ((ref y, _) | (_, ref y),) => y,
27+
| ----- immutable borrow occurs here
28+
LL | };
29+
LL | &mut x.0 .0;
30+
| ^^^^^^^^^^^ mutable borrow occurs here
31+
...
32+
LL | drop(r);
33+
| - immutable borrow later used here
34+
35+
error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable
36+
--> $DIR/or-patterns.rs:22:5
37+
|
38+
LL | ((ref y, _) | (_, ref y),) => y,
39+
| ----- immutable borrow occurs here
40+
...
41+
LL | &mut x.0 .1;
42+
| ^^^^^^^^^^^ mutable borrow occurs here
43+
LL |
44+
LL | drop(r);
45+
| - immutable borrow later used here
46+
47+
error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable
48+
--> $DIR/or-patterns.rs:31:5
49+
|
50+
LL | ((ref mut y, _) | (_, ref mut y),) => y,
51+
| --------- mutable borrow occurs here
52+
LL | };
53+
LL | &x.0 .0;
54+
| ^^^^^^^ immutable borrow occurs here
55+
...
56+
LL | drop(r);
57+
| - mutable borrow later used here
58+
59+
error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable
60+
--> $DIR/or-patterns.rs:33:5
61+
|
62+
LL | ((ref mut y, _) | (_, ref mut y),) => y,
63+
| --------- mutable borrow occurs here
64+
...
65+
LL | &x.0 .1;
66+
| ^^^^^^^ immutable borrow occurs here
67+
LL |
68+
LL | drop(r);
69+
| - mutable borrow later used here
70+
71+
error[E0382]: borrow of moved value: `x.0.0`
72+
--> $DIR/or-patterns.rs:40:5
73+
|
74+
LL | let ((y, _) | (_, y),) = x;
75+
| - value moved here
76+
LL | &x.0 .0;
77+
| ^^^^^^^ value borrowed here after move
78+
|
79+
= note: move occurs because `x.0.0` has type `std::string::String`, which does not implement the `Copy` trait
80+
81+
error[E0382]: borrow of moved value: `x.0.1`
82+
--> $DIR/or-patterns.rs:42:5
83+
|
84+
LL | let ((y, _) | (_, y),) = x;
85+
| - value moved here
86+
...
87+
LL | &x.0 .1;
88+
| ^^^^^^^ value borrowed here after move
89+
|
90+
= note: move occurs because `x.0.1` has type `std::string::String`, which does not implement the `Copy` trait
91+
92+
error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
93+
--> $DIR/or-patterns.rs:48:5
94+
|
95+
LL | let ((ref r, _) | (_, ref r),) = x;
96+
| ----- immutable borrow occurs here
97+
LL | &mut x.0 .0;
98+
| ^^^^^^^^^^^ mutable borrow occurs here
99+
...
100+
LL | drop(r);
101+
| - immutable borrow later used here
102+
103+
error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable
104+
--> $DIR/or-patterns.rs:50:5
105+
|
106+
LL | let ((ref r, _) | (_, ref r),) = x;
107+
| ----- immutable borrow occurs here
108+
...
109+
LL | &mut x.0 .1;
110+
| ^^^^^^^^^^^ mutable borrow occurs here
111+
LL |
112+
LL | drop(r);
113+
| - immutable borrow later used here
114+
115+
error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable
116+
--> $DIR/or-patterns.rs:57:5
117+
|
118+
LL | let ((ref mut r, _) | (_, ref mut r),) = x;
119+
| --------- mutable borrow occurs here
120+
LL | &x.0 .0;
121+
| ^^^^^^^ immutable borrow occurs here
122+
...
123+
LL | drop(r);
124+
| - mutable borrow later used here
125+
126+
error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable
127+
--> $DIR/or-patterns.rs:59:5
128+
|
129+
LL | let ((ref mut r, _) | (_, ref mut r),) = x;
130+
| --------- mutable borrow occurs here
131+
...
132+
LL | &x.0 .1;
133+
| ^^^^^^^ immutable borrow occurs here
134+
LL |
135+
LL | drop(r);
136+
| - mutable borrow later used here
137+
138+
error: aborting due to 12 previous errors
139+
140+
Some errors have detailed explanations: E0382, E0502.
141+
For more information about an error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-pass
2+
3+
#![feature(or_patterns)]
4+
5+
fn two_bindings(x: &((bool, bool), u8)) -> u8 {
6+
match x {
7+
&((true, y) | (y, true), z @ (0 | 4)) => (y as u8) + z,
8+
_ => 20,
9+
}
10+
}
11+
12+
fn main() {
13+
assert_eq!(two_bindings(&((false, false), 0)), 20);
14+
assert_eq!(two_bindings(&((false, true), 0)), 0);
15+
assert_eq!(two_bindings(&((true, false), 0)), 0);
16+
assert_eq!(two_bindings(&((true, true), 0)), 1);
17+
assert_eq!(two_bindings(&((false, false), 4)), 20);
18+
assert_eq!(two_bindings(&((false, true), 4)), 4);
19+
assert_eq!(two_bindings(&((true, false), 4)), 4);
20+
assert_eq!(two_bindings(&((true, true), 4)), 5);
21+
assert_eq!(two_bindings(&((false, false), 3)), 20);
22+
assert_eq!(two_bindings(&((false, true), 3)), 20);
23+
assert_eq!(two_bindings(&((true, false), 3)), 20);
24+
assert_eq!(two_bindings(&((true, true), 3)), 20);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// run-pass
2+
3+
#![feature(or_patterns)]
4+
5+
fn or_at(x: Result<u32, u32>) -> u32 {
6+
match x {
7+
Ok(x @ 4) | Err(x @ (6 | 8)) => x,
8+
Ok(x @ 1 | x @ 2) => x,
9+
Err(x @ (0..=10 | 30..=40)) if x % 2 == 0 => x + 100,
10+
Err(x @ 0..=40) => x + 200,
11+
_ => 500,
12+
}
13+
}
14+
15+
fn main() {
16+
assert_eq!(or_at(Ok(1)), 1);
17+
assert_eq!(or_at(Ok(2)), 2);
18+
assert_eq!(or_at(Ok(3)), 500);
19+
assert_eq!(or_at(Ok(4)), 4);
20+
assert_eq!(or_at(Ok(5)), 500);
21+
assert_eq!(or_at(Ok(6)), 500);
22+
assert_eq!(or_at(Err(1)), 201);
23+
assert_eq!(or_at(Err(2)), 102);
24+
assert_eq!(or_at(Err(3)), 203);
25+
assert_eq!(or_at(Err(4)), 104);
26+
assert_eq!(or_at(Err(5)), 205);
27+
assert_eq!(or_at(Err(6)), 6);
28+
assert_eq!(or_at(Err(7)), 207);
29+
assert_eq!(or_at(Err(8)), 8);
30+
assert_eq!(or_at(Err(20)), 220);
31+
assert_eq!(or_at(Err(50)), 500);
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Check that we don't ICE for irrefutable or-patterns in function parameters
2+
3+
// check-pass
4+
5+
#![feature(or_patterns)]
6+
7+
fn foo((Some(_) | None): Option<u32>) {}
8+
9+
fn main() {
10+
foo(None);
11+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(or_patterns)]
2+
3+
// run-pass
4+
5+
fn or_pat_let(x: Result<u32, u32>) -> u32 {
6+
let Ok(y) | Err(y) = x;
7+
y
8+
}
9+
10+
fn or_pat_arg((Ok(y) | Err(y)): Result<u32, u32>) -> u32 {
11+
y
12+
}
13+
14+
fn main() {
15+
assert_eq!(or_pat_let(Ok(3)), 3);
16+
assert_eq!(or_pat_let(Err(5)), 5);
17+
assert_eq!(or_pat_arg(Ok(7)), 7);
18+
assert_eq!(or_pat_arg(Err(9)), 9);
19+
}

0 commit comments

Comments
 (0)