Skip to content

Commit 91a3db9

Browse files
committed
Add check for overlapping ranges to unreachable patterns lint
1 parent 237d54f commit 91a3db9

11 files changed

+325
-118
lines changed

src/libcore/ascii.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ pub fn escape_default(c: u8) -> EscapeDefault {
100100
b'\\' => ([b'\\', b'\\', 0, 0], 2),
101101
b'\'' => ([b'\\', b'\'', 0, 0], 2),
102102
b'"' => ([b'\\', b'"', 0, 0], 2),
103+
// The three arms above are in the following range
104+
#[allow(unreachable_patterns)]
103105
b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1),
104106
_ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
105107
};

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 170 additions & 60 deletions
Large diffs are not rendered by default.

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
1010
use rustc::lint;
1111
use rustc_errors::{Applicability, DiagnosticBuilder};
1212

13+
use rustc::hir::HirId;
1314
use rustc::hir::def::*;
1415
use rustc::hir::def_id::DefId;
1516
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -239,7 +240,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
239240
.map(|pat| smallvec![pat.0])
240241
.collect();
241242
let scrut_ty = self.tables.node_type(scrut.hir_id);
242-
check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
243+
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
243244
})
244245
}
245246

@@ -256,7 +257,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
256257
expand_pattern(cx, pattern)
257258
]].into_iter().collect();
258259

259-
let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
260+
let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
260261
Ok(_) => return,
261262
Err(err) => err,
262263
};
@@ -389,7 +390,7 @@ fn check_arms<'tcx>(
389390
for &(pat, hir_pat) in pats {
390391
let v = smallvec![pat];
391392

392-
match is_useful(cx, &seen, &v, LeaveOutWitness) {
393+
match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
393394
NotUseful => {
394395
match source {
395396
hir::MatchSource::IfDesugar { .. } |
@@ -428,6 +429,13 @@ fn check_arms<'tcx>(
428429

429430
hir::MatchSource::ForLoopDesugar |
430431
hir::MatchSource::Normal => {
432+
match pat.kind {
433+
box PatternKind::Range(..) => {
434+
// Covered in `is_useful() with more context`
435+
break;
436+
}
437+
_ => {}
438+
}
431439
let mut err = cx.tcx.struct_span_lint_hir(
432440
lint::builtin::UNREACHABLE_PATTERNS,
433441
hir_pat.hir_id,
@@ -465,9 +473,10 @@ fn check_not_useful(
465473
cx: &mut MatchCheckCtxt<'_, 'tcx>,
466474
ty: Ty<'tcx>,
467475
matrix: &Matrix<'_, 'tcx>,
476+
hir_id: HirId,
468477
) -> Result<(), Vec<super::Pat<'tcx>>> {
469478
let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
470-
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
479+
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) {
471480
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
472481
UsefulWithWitness(pats) => Err(if pats.is_empty() {
473482
vec![wild_pattern]
@@ -483,8 +492,9 @@ fn check_exhaustive<'tcx>(
483492
scrut_ty: Ty<'tcx>,
484493
sp: Span,
485494
matrix: &Matrix<'_, 'tcx>,
495+
hir_id: HirId,
486496
) {
487-
let witnesses = match check_not_useful(cx, scrut_ty, matrix) {
497+
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
488498
Ok(_) => return,
489499
Err(err) => err,
490500
};

src/test/ui/check_match/issue-43253.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// build-pass (FIXME(62277): could be check-pass?)
1+
// check-pass
22

33
#![feature(exclusive_range_pattern)]
44
#![warn(unreachable_patterns)]
@@ -13,7 +13,7 @@ fn main() {
1313

1414
match 10 {
1515
1..10 => {},
16-
9..=10 => {},
16+
9..=10 => {}, //~ WARNING multiple patterns covering the same range
1717
_ => {},
1818
}
1919

@@ -23,22 +23,25 @@ fn main() {
2323
_ => {},
2424
}
2525

26-
// These cases should generate an "unreachable pattern" warning.
26+
// These cases should generate "unreachable pattern" warnings.
2727
match 10 {
2828
1..10 => {},
29-
9 => {},
29+
9 => {}, //~ WARNING unreachable pattern
3030
_ => {},
3131
}
3232

3333
match 10 {
3434
1..10 => {},
35-
8..=9 => {},
35+
8..=9 => {}, //~ WARNING multiple patterns covering the same range
3636
_ => {},
3737
}
3838

3939
match 10 {
40-
1..10 => {},
41-
9..=9 => {},
40+
5..7 => {},
41+
6 => {}, //~ WARNING unreachable pattern
42+
1..10 => {}, //~ WARNING multiple patterns covering the same range
43+
9..=9 => {}, //~ WARNING unreachable pattern
44+
6 => {}, //~ WARNING unreachable pattern
4245
_ => {},
4346
}
4447
}
Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
warning: unreachable pattern
2-
--> $DIR/issue-43253.rs:29:9
1+
warning: multiple patterns covering the same range
2+
--> $DIR/issue-43253.rs:16:9
33
|
4-
LL | 9 => {},
5-
| ^
4+
LL | 1..10 => {},
5+
| ----- this range overlaps on `9i32`
6+
LL | 9..=10 => {},
7+
| ^^^^^^ overlapping patterns
68
|
79
note: lint level defined here
810
--> $DIR/issue-43253.rs:4:9
@@ -11,14 +13,44 @@ LL | #![warn(unreachable_patterns)]
1113
| ^^^^^^^^^^^^^^^^^^^^
1214

1315
warning: unreachable pattern
16+
--> $DIR/issue-43253.rs:29:9
17+
|
18+
LL | 9 => {},
19+
| ^
20+
21+
warning: multiple patterns covering the same range
1422
--> $DIR/issue-43253.rs:35:9
1523
|
24+
LL | 1..10 => {},
25+
| ----- this range overlaps on `8i32..=9i32`
1626
LL | 8..=9 => {},
17-
| ^^^^^
27+
| ^^^^^ overlapping patterns
1828

1929
warning: unreachable pattern
2030
--> $DIR/issue-43253.rs:41:9
2131
|
32+
LL | 6 => {},
33+
| ^
34+
35+
warning: multiple patterns covering the same range
36+
--> $DIR/issue-43253.rs:42:9
37+
|
38+
LL | 5..7 => {},
39+
| ---- this range overlaps on `5i32..=6i32`
40+
LL | 6 => {},
41+
| - this range overlaps on `6i32`
42+
LL | 1..10 => {},
43+
| ^^^^^ overlapping patterns
44+
45+
warning: unreachable pattern
46+
--> $DIR/issue-43253.rs:43:9
47+
|
2248
LL | 9..=9 => {},
2349
| ^^^^^
2450

51+
warning: unreachable pattern
52+
--> $DIR/issue-43253.rs:44:9
53+
|
54+
LL | 6 => {},
55+
| ^
56+

src/test/ui/exhaustive_integer_patterns.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn main() {
1919
0 ..= 32 => {}
2020
33 => {}
2121
34 .. 128 => {}
22-
100 ..= 200 => {}
22+
100 ..= 200 => {} //~ ERROR multiple patterns covering the same range
2323
200 => {} //~ ERROR unreachable pattern
2424
201 ..= 255 => {}
2525
}
@@ -41,7 +41,7 @@ fn main() {
4141
match x { //~ ERROR non-exhaustive patterns
4242
-7 => {}
4343
-5..=120 => {}
44-
-2..=20 => {} //~ ERROR unreachable pattern
44+
-2..=20 => {} //~ ERROR multiple patterns covering the same range
4545
125 => {}
4646
}
4747

@@ -135,9 +135,9 @@ fn main() {
135135
(125 .. 128, false) => {}
136136
}
137137

138-
match 0u8 { // ok
138+
match 0u8 {
139139
0 .. 2 => {}
140-
1 ..= 2 => {}
140+
1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
141141
_ => {}
142142
}
143143

src/test/ui/exhaustive_integer_patterns.stderr

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
error: unreachable pattern
2-
--> $DIR/exhaustive_integer_patterns.rs:23:9
1+
error: multiple patterns covering the same range
2+
--> $DIR/exhaustive_integer_patterns.rs:22:9
33
|
4-
LL | 200 => {}
5-
| ^^^
4+
LL | 34 .. 128 => {}
5+
| --------- this range overlaps on `100u8..=127u8`
6+
LL | 100 ..= 200 => {}
7+
| ^^^^^^^^^^^ overlapping patterns
68
|
79
note: lint level defined here
810
--> $DIR/exhaustive_integer_patterns.rs:4:9
911
|
1012
LL | #![deny(unreachable_patterns)]
1113
| ^^^^^^^^^^^^^^^^^^^^
1214

15+
error: unreachable pattern
16+
--> $DIR/exhaustive_integer_patterns.rs:23:9
17+
|
18+
LL | 200 => {}
19+
| ^^^
20+
1321
error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
1422
--> $DIR/exhaustive_integer_patterns.rs:28:11
1523
|
@@ -26,11 +34,13 @@ LL | match x {
2634
|
2735
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2836

29-
error: unreachable pattern
37+
error: multiple patterns covering the same range
3038
--> $DIR/exhaustive_integer_patterns.rs:44:9
3139
|
40+
LL | -5..=120 => {}
41+
| -------- this range overlaps on `-2i8..=20i8`
3242
LL | -2..=20 => {}
33-
| ^^^^^^^
43+
| ^^^^^^^ overlapping patterns
3444

3545
error[E0004]: non-exhaustive patterns: `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
3646
--> $DIR/exhaustive_integer_patterns.rs:41:11
@@ -80,6 +90,14 @@ LL | match (0u8, true) {
8090
|
8191
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8292

93+
error: multiple patterns covering the same range
94+
--> $DIR/exhaustive_integer_patterns.rs:140:9
95+
|
96+
LL | 0 .. 2 => {}
97+
| ------ this range overlaps on `1u8`
98+
LL | 1 ..= 2 => {}
99+
| ^^^^^^^ overlapping patterns
100+
83101
error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
84102
--> $DIR/exhaustive_integer_patterns.rs:145:11
85103
|
@@ -104,6 +122,6 @@ LL | match 0u128 {
104122
|
105123
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
106124

107-
error: aborting due to 13 previous errors
125+
error: aborting due to 15 previous errors
108126

109127
For more information about this error, try `rustc --explain E0004`.
Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,41 @@
1-
//error-pattern: unreachable
2-
//error-pattern: unreachable
3-
//error-pattern: unreachable
4-
//error-pattern: unreachable
5-
//error-pattern: unreachable
6-
71
#![deny(unreachable_patterns)]
82

93
fn main() {
104
match 5 {
115
1 ..= 10 => { }
12-
5 ..= 6 => { }
6+
5 ..= 6 => { } //~ ERROR multiple patterns covering the same range
137
_ => {}
148
};
159

1610
match 5 {
1711
3 ..= 6 => { }
18-
4 ..= 6 => { }
12+
4 ..= 6 => { } //~ ERROR multiple patterns covering the same range
1913
_ => {}
2014
};
2115

2216
match 5 {
2317
4 ..= 6 => { }
24-
4 ..= 6 => { }
18+
4 ..= 6 => { } //~ ERROR multiple patterns covering the same range
2519
_ => {}
2620
};
2721

2822
match 'c' {
2923
'A' ..= 'z' => {}
30-
'a' ..= 'z' => {}
24+
'a' ..= 'z' => {} //~ ERROR multiple patterns covering the same range
3125
_ => {}
3226
};
3327

3428
match 1.0f64 {
3529
0.01f64 ..= 6.5f64 => {}
36-
0.02f64 => {}
30+
//~^ WARNING floating-point types cannot be used in patterns
31+
//~| WARNING floating-point types cannot be used in patterns
32+
//~| WARNING floating-point types cannot be used in patterns
33+
//~| WARNING this was previously accepted by the compiler
34+
//~| WARNING this was previously accepted by the compiler
35+
//~| WARNING this was previously accepted by the compiler
36+
0.02f64 => {} //~ ERROR unreachable pattern
37+
//~^ WARNING floating-point types cannot be used in patterns
38+
//~| WARNING this was previously accepted by the compiler
3739
_ => {}
3840
};
3941
}

0 commit comments

Comments
 (0)