10000 Add check for overlapping ranges to unreachable patterns lint by estebank · Pull Request #64007 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content

Add check for overlapping ranges to unreachable patterns lint #64007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 19, 2019
Next Next commit
Add check for overlapping ranges to unreachable patterns lint
  • Loading branch information
estebank committed Oct 16, 2019
commit 91a3db95a1a5939054d72d2ce69c5647c3cfb93b
2 changes: 2 additions & 0 deletions src/libcore/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ pub fn escape_default(c: u8) -> EscapeDefault {
b'\\' => ([b'\\', b'\\', 0, 0], 2),
b'\'' => ([b'\\', b'\'', 0, 0], 2),
b'"' => ([b'\\', b'"', 0, 0], 2),
// The three arms above are in the following range
#[allow(unreachable_patterns)]
b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1),
_ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
};
Expand Down
230 changes: 170 additions & 60 deletions src/librustc_mir/hair/pattern/_match.rs

Large diffs are not rendered by default.

20 changes: 15 additions & 5 deletions src/librustc_mir/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::lint;
use rustc_errors::{Applicability, DiagnosticBuilder};

use rustc::hir::HirId;
use rustc::hir::def::*;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
Expand Down Expand Up @@ -239,7 +240,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
.map(|pat| smallvec![pat.0])
.collect();
let scrut_ty = self.tables.node_type(scrut.hir_id);
check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
})
}

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

let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
Ok(_) => return,
Err(err) => err,
};
Expand Down Expand Up @@ -389,7 +390,7 @@ fn check_arms<'tcx>(
for &(pat, hir_pat) in pats {
let v = smallvec![pat];

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

hir::MatchSource::ForLoopDesugar |
hir::MatchSource::Normal => {
match pat.kind {
box PatternKind::Range(..) => {
// Covered in `is_useful() with more context`
break;
}
_ => {}
}
let mut err = cx.tcx.struct_span_lint_hir(
lint::builtin::UNREACHABLE_PATTERNS,
hir_pat.hir_id,
Expand Down Expand Up @@ -465,9 +473,10 @@ fn check_not_useful(
cx: &mut MatchCheckCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
matrix: &Matrix<'_, 'tcx>,
hir_id: HirId,
) -> Result<(), Vec<super::Pat<'tcx>>> {
let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) {
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
UsefulWithWitness(pats) => Err(if pats.is_empty() {
vec![wild_pattern]
Expand All @@ -483,8 +492,9 @@ fn check_exhaustive<'tcx>(
scrut_ty: Ty<'tcx>,
sp: Span,
matrix: &Matrix<'_, 'tcx>,
hir_id: HirId,
) {
let witnesses = match check_not_useful(cx, scrut_ty, matrix) {
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
Ok(_) => return,
Err(err) => err,
};
Expand Down
17 changes: 10 additions & 7 deletions src/test/ui/check_match/issue-43253.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?)
// check-pass

#![feature(exclusive_range_pattern)]
#![warn(unreachable_patterns)]
Expand All @@ -13,7 +13,7 @@ fn main() {

match 10 {
1..10 => {},
9..=10 => {},
9..=10 => {}, //~ WARNING multiple patterns covering the same range
_ => {},
}

Expand All @@ -23,22 +23,25 @@ fn main() {
_ => {},
}

// These cases should generate an "unreachable pattern" warning.
// These cases should generate "unreachable pattern" warnings.
match 10 {
1..10 => {},
9 => {},
9 => {}, //~ WARNING unreachable pattern
_ => {},
}

match 10 {
1..10 => {},
8..=9 => {},
8..=9 => {}, //~ WARNING multiple patterns covering the same range
_ => {},
}

match 10 {
1..10 => {},
9..=9 => {},
5..7 => {},
6 => {}, //~ WARNING unreachable pattern
1..10 => {}, //~ WARNING multiple patterns covering the same range
9..=9 => {}, //~ WARNING unreachable pattern
6 => {}, //~ WARNING unreachable pattern
_ => {},
}
}
42 changes: 37 additions & 5 deletions src/test/ui/check_match/issue-43253.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
warning: unreachable pattern
--> $DIR/issue-43253.rs:29:9
warning: multiple patterns covering the same range
--> $DIR/issue-43253.rs:16:9
|
LL | 9 => {},
| ^
LL | 1..10 => {},
| ----- this range overlaps on `9i32`
LL | 9..=10 => {},
| ^^^^^^ overlapping patterns
|
note: lint level defined here
--> $DIR/issue-43253.rs:4:9
Expand All @@ -11,14 +13,44 @@ LL | #![warn(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^

warning: unreachable pattern
--> $DIR/issue-43253.rs:29:9
|
LL | 9 => {},
| ^

warning: multiple patterns covering the same range
--> $DIR/issue-43253.rs:35:9
|
LL | 1..10 => {},
| ----- this range overlaps on `8i32..=9i32`
LL | 8..=9 => {},
| ^^^^^
| ^^^^^ overlapping patterns

warning: unreachable pattern
--> $DIR/issue-43253.rs:41:9
|
LL | 6 => {},
| ^

warning: multiple patterns covering the same range
--> $DIR/issue-43253.rs:42:9
|
LL | 5..7 => {},
| ---- this range overlaps on `5i32..=6i32`
LL | 6 => {},
| - this range overlaps on `6i32`
LL | 1..10 => {},
| ^^^^^ overlapping patterns

warning: unreachable pattern
--> $DIR/issue-43253.rs:43:9
|
LL | 9..=9 => {},
| ^^^^^

warning: unreachable pattern
--> $DIR/issue-43253.rs:44:9
|
LL | 6 => {},
| ^

8 changes: 4 additions & 4 deletions src/test/ui/exhaustive_integer_patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {
0 ..= 32 => {}
33 => {}
34 .. 128 => {}
100 ..= 200 => {}
100 ..= 200 => {} //~ ERROR multiple patterns covering the same range
200 => {} //~ ERROR unreachable pattern
201 ..= 255 => {}
}
Expand All @@ -41,7 +41,7 @@ fn main() {
match x { //~ ERROR non-exhaustive patterns
-7 => {}
-5..=120 => {}
-2..=20 => {} //~ ERROR unreachable pattern
-2..=20 => {} //~ ERROR multiple patterns covering the same range
125 => {}
}

Expand Down Expand Up @@ -135,9 +135,9 @@ fn main() {
(125 .. 128, false) => {}
}

match 0u8 { // ok
match 0u8 {
0 .. 2 => {}
1 ..= 2 => {}
1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
_ => {}
}

Expand Down
32 changes: 25 additions & 7 deletions src/test/ui/exhaustive_integer_patterns.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
error: unreachable pattern
--> $DIR/exhaustive_integer_patterns.rs:23:9
error: multiple patterns covering the same range
--> $DIR/exhaustive_integer_patterns.rs:22:9
|
LL | 200 => {}
| ^^^
LL | 34 .. 128 => {}
| --------- this range overlaps on `100u8..=127u8`
LL | 100 ..= 200 => {}
| ^^^^^^^^^^^ overlapping patterns
|
note: lint level defined here
--> $DIR/exhaustive_integer_patterns.rs:4:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/exhaustive_integer_patterns.rs:23:9
|
LL | 200 => {}
| ^^^

error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
--> $DIR/exhaustive_integer_patterns.rs:28:11
|
Expand All @@ -26,11 +34,13 @@ LL | match x {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error: unreachable pattern
error: multiple patterns covering the same range
--> $DIR/exhaustive_integer_patterns.rs:44:9
|
LL | -5..=120 => {}
| -------- this range overlaps on `-2i8..=20i8`
LL | -2..=20 => {}
| ^^^^^^^
| ^^^^^^^ overlapping patterns

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

error: multiple patterns covering the same range
--> $DIR/exhaustive_integer_patterns.rs:140:9
|
LL | 0 .. 2 => {}
| ------ this range overlaps on `1u8`
LL | 1 ..= 2 => {}
| ^^^^^^^ overlapping patterns

error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
--> $DIR/exhaustive_integer_patterns.rs:145:11
|
Expand All @@ -104,6 +122,6 @@ LL | match 0u128 {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error: aborting due to 13 previous errors
error: aborting due to 15 previous errors

For more information about this error, try `rustc --explain E0004`.
24 changes: 13 additions & 11 deletions src/test/ui/match/match-range-fail-dominate.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
//error-pattern: unreachable
//error-pattern: unreachable
//error-pattern: unreachable
//error-pattern: unreachable
//error-pattern: unreachable

#![deny(unreachable_patterns)]

fn main() {
match 5 {
1 ..= 10 => { }
5 ..= 6 => { }
5 ..= 6 => { } //~ ERROR multiple patterns covering the same range
_ => {}
};

match 5 {
3 ..= 6 => { }
4 ..= 6 => { }
4 ..= 6 => { } //~ ERROR multiple patterns covering the same range
_ => {}
};

match 5 {
4 ..= 6 => { }
4 ..= 6 => { }
4 ..= 6 => { } //~ ERROR multiple patterns covering the same range
_ => {}
};

match 'c' {
'A' ..= 'z' => {}
'a' ..= 'z' => {}
'a' ..= 'z' => {} //~ ERROR multiple patterns covering the same range
_ => {}
};

match 1.0f64 {
0.01f64 ..= 6.5f64 => {}
0.02f64 => {}
//~^ WARNING floating-point types cannot be used in patterns
//~| WARNING floating-point types cannot be used in patterns
//~| WARNING floating-point types cannot be used in patterns
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
0.02f64 => {} //~ ERROR unreachable pattern
//~^ WARNING floating-point types cannot be used in patterns
//~| WARNING this was previously accepted by the compiler
_ => {}
};
}
Loading
0