/
exhaustive_integer_patterns.rs
158 lines (129 loc) · 3.56 KB
/
exhaustive_integer_patterns.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#![feature(precise_pointer_size_matching)]
#![feature(exclusive_range_pattern)]
#![deny(unreachable_patterns)]
#![deny(overlapping_patterns)]
use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128};
fn main() {
let x: u8 = 0;
// A single range covering the entire domain.
match x {
0 ..= 255 => {} // ok
}
// A combination of ranges and values.
// These are currently allowed to be overlapping.
match x {
0 ..= 32 => {}
33 => {}
34 .. 128 => {}
100 ..= 200 => {} //~ ERROR multiple patterns covering the same range
200 => {} //~ ERROR unreachable pattern
201 ..= 255 => {}
}
// An incomplete set of values.
match x { //~ ERROR non-exhaustive patterns
0 .. 128 => {}
}
// A more incomplete set of values.
match x { //~ ERROR non-exhaustive patterns
0 ..= 10 => {}
20 ..= 30 => {}
35 => {}
70 .. 255 => {}
}
let x: i8 = 0;
match x { //~ ERROR non-exhaustive patterns
-7 => {}
-5..=120 => {}
-2..=20 => {}
//~^ ERROR unreachable pattern
//~| ERROR multiple patterns covering the same range
125 => {}
}
// Let's test other types too!
let c: char = '\u{0}';
match c {
'\u{0}' ..= char::MAX => {} // ok
}
// We can actually get away with just covering the
// following two ranges, which correspond to all
// valid Unicode Scalar Values.
match c {
'\u{0000}' ..= '\u{D7FF}' => {}
'\u{E000}' ..= '\u{10_FFFF}' => {}
}
match 0u16 {
0 ..= u16::MAX => {} // ok
}
match 0u32 {
0 ..= u32::MAX => {} // ok
}
match 0u64 {
0 ..= u64::MAX => {} // ok
}
match 0u128 {
0 ..= u128::MAX => {} // ok
}
match 0i8 {
-128 ..= 127 => {} // ok
}
match 0i8 { //~ ERROR non-exhaustive patterns
-127 ..= 127 => {}
}
match 0i16 {
i16::MIN ..= i16::MAX => {} // ok
}
match 0i16 { //~ ERROR non-exhaustive patterns
i16::MIN ..= -1 => {}
1 ..= i16::MAX => {}
}
match 0i32 {
i32::MIN ..= i32::MAX => {} // ok
}
match 0i64 {
i64::MIN ..= i64::MAX => {} // ok
}
match 0i128 {
i128::MIN ..= i128::MAX => {} // ok
}
// Make sure that guards don't factor into the exhaustiveness checks.
match 0u8 { //~ ERROR non-exhaustive patterns
0 .. 128 => {}
128 ..= 255 if true => {}
}
match 0u8 {
0 .. 128 => {}
128 ..= 255 if false => {}
128 ..= 255 => {} // ok, because previous arm was guarded
}
// Now things start getting a bit more interesting. Testing products!
match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
(1, _) => {}
(_, None) => {}
}
match (0u8, true) { //~ ERROR non-exhaustive patterns
(0 ..= 125, false) => {}
(128 ..= 255, false) => {}
(0 ..= 255, true) => {}
}
match (0u8, true) { // ok
(0 ..= 125, false) => {}
(128 ..= 255, false) => {}
(0 ..= 255, true) => {}
(125 .. 128, false) => {}
}
match 0u8 {
0 .. 2 => {}
1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
_ => {}
}
const LIM: u128 = u128::MAX - 1;
match 0u128 { //~ ERROR non-exhaustive patterns
0 ..= LIM => {}
}
match 0u128 { //~ ERROR non-exhaustive patterns
0 ..= 4 => {}
}
match 0u128 { //~ ERROR non-exhaustive patterns
4 ..= u128::MAX => {}
}
}