Auto merge of #80632 - Nadrieril:fix-80501, r=varkor
Identify unreachable subpatterns more reliably In https://github.com/rust-lang/rust/pull/80104 I used `Span`s to identify unreachable sub-patterns in the presence of or-patterns during exhaustiveness checking. In https://github.com/rust-lang/rust/issues/80501 it was revealed that `Span`s are complicated and that this was not a good idea. Instead, this PR identifies subpatterns logically: as a path in the tree of subpatterns of a given pattern. I made a struct that captures a set of such subpatterns. This is a bit complex, but thankfully self-contained; the rest of the code does not need to know anything about it. Fixes https://github.com/rust-lang/rust/issues/80501. I think I managed to keep the perf neutral. r? `@varkor`
This commit is contained in:
commit
36ecbc94eb
6 changed files with 473 additions and 224 deletions
|
|
@ -48,6 +48,25 @@ fn main() {
|
|||
(1 | 1,) => {} //~ ERROR unreachable
|
||||
_ => {}
|
||||
}
|
||||
match 0 {
|
||||
(0 | 1) | 1 => {} //~ ERROR unreachable
|
||||
_ => {}
|
||||
}
|
||||
match 0 {
|
||||
// We get two errors because recursive or-pattern expansion means we don't notice the two
|
||||
// errors span a whole pattern. This could be better but doesn't matter much
|
||||
0 | (0 | 0) => {}
|
||||
//~^ ERROR unreachable
|
||||
//~| ERROR unreachable
|
||||
_ => {}
|
||||
}
|
||||
match None {
|
||||
// There is only one error that correctly points to the whole subpattern
|
||||
Some(0) |
|
||||
Some( //~ ERROR unreachable
|
||||
0 | 0) => {}
|
||||
_ => {}
|
||||
}
|
||||
match [0; 2] {
|
||||
[0
|
||||
| 0 //~ ERROR unreachable
|
||||
|
|
@ -84,8 +103,8 @@ fn main() {
|
|||
}
|
||||
macro_rules! t_or_f {
|
||||
() => {
|
||||
(true // FIXME: should be unreachable
|
||||
| false)
|
||||
(true //~ ERROR unreachable
|
||||
| false)
|
||||
};
|
||||
}
|
||||
match (true, None) {
|
||||
|
|
|
|||
|
|
@ -77,58 +77,94 @@ LL | (1 | 1,) => {}
|
|||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:53:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:52:19
|
||||
|
|
||||
LL | (0 | 1) | 1 => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:14
|
||||
|
|
||||
LL | 0 | (0 | 0) => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:18
|
||||
|
|
||||
LL | 0 | (0 | 0) => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:13
|
||||
|
|
||||
LL | / Some(
|
||||
LL | | 0 | 0) => {}
|
||||
| |______________________^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:72:15
|
||||
|
|
||||
LL | | 0
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:55:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:74:15
|
||||
|
|
||||
LL | | 0] => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:63:10
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:82:10
|
||||
|
|
||||
LL | [1
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:75:10
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:94:10
|
||||
|
|
||||
LL | [true
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:82:36
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:101:36
|
||||
|
|
||||
LL | (true | false, None | Some(true
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:98:14
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:106:14
|
||||
|
|
||||
LL | (true
|
||||
| ^^^^
|
||||
...
|
||||
LL | (true | false, None | Some(t_or_f!())) => {}
|
||||
| --------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:117:14
|
||||
|
|
||||
LL | Some(0
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:117:19
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:136:19
|
||||
|
|
||||
LL | | false) => {}
|
||||
| ^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:125:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:144:15
|
||||
|
|
||||
LL | | true) => {}
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:131:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:150:15
|
||||
|
|
||||
LL | | true,
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// check-pass
|
||||
#![deny(unreachable_patterns)]
|
||||
pub enum TypeCtor {
|
||||
Slice,
|
||||
Array,
|
||||
}
|
||||
|
||||
pub struct ApplicationTy(TypeCtor);
|
||||
|
||||
macro_rules! ty_app {
|
||||
($ctor:pat) => {
|
||||
ApplicationTy($ctor)
|
||||
};
|
||||
}
|
||||
|
||||
fn _foo(ty: ApplicationTy) {
|
||||
match ty {
|
||||
ty_app!(TypeCtor::Array) | ty_app!(TypeCtor::Slice) => {}
|
||||
}
|
||||
|
||||
// same as above, with the macro expanded
|
||||
match ty {
|
||||
ApplicationTy(TypeCtor::Array) | ApplicationTy(TypeCtor::Slice) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue