Skip to content
Permalink
Browse files

Add check for overlapping ranges to unreachable patterns lint

  • Loading branch information...
estebank committed Aug 29, 2019
1 parent 53df91a commit 2731c02d8bc80f1de118ad0fe4e26bc7186657bd
@@ -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),
};
@@ -303,6 +303,8 @@ impl char {
'\r' => EscapeDefaultState::Backslash('r'),
'\n' => EscapeDefaultState::Backslash('n'),
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
// The three patterns above are in the following range
#[allow(unreachable_patterns)]
'\x20' ..= '\x7e' => EscapeDefaultState::Char(self),
_ => EscapeDefaultState::Unicode(self.escape_unicode())
};

Large diffs are not rendered by default.

@@ -16,6 +16,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};
@@ -260,7 +261,7 @@ impl<'a, 'tcx> MatchVisitor<'a, '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);
})
}

@@ -282,7 +283,13 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
span: DUMMY_SP,
kind: box PatternKind::Wild,
};
let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) {
let witness = match is_useful(
cx,
&pats,
&[&wild_pattern],
ConstructWitness,
pat.hir_id,
) {
UsefulWithWitness(witness) => witness,
NotUseful => return,
Useful => bug!()
@@ -373,7 +380,7 @@ fn check_arms<'a, '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 { .. } |
@@ -412,6 +419,13 @@ fn check_arms<'a, '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,
@@ -450,13 +464,14 @@ fn check_exhaustive<'p, 'a, 'tcx>(
scrut_ty: Ty<'tcx>,
sp: Span,
matrix: &Matrix<'p, 'tcx>,
hir_id: HirId,
) {
let wild_pattern = Pattern {
ty: scrut_ty,
span: DUMMY_SP,
kind: box PatternKind::Wild,
};
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) {
UsefulWithWitness(pats) => {
let witnesses = if pats.is_empty() {
vec![&wild_pattern]
@@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?)
// check-pass

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

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

@@ -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
_ => {},
}
}
@@ -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
@@ -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 => {},
| ^

@@ -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 => {}
}
@@ -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 => {}
}

@@ -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
_ => {}
}

@@ -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
|
@@ -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
@@ -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
|
@@ -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`.
@@ -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
_ => {}
};
}

0 comments on commit 2731c02

Please sign in to comment.
You can’t perform that action at this time.