diff options
| author | bors <bors@rust-lang.org> | 2021-02-07 16:48:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-02-07 16:48:57 +0000 |
| commit | 36ecbc94eb6be90bc38b2d0fdd4bfac3f34d9923 (patch) | |
| tree | d74ad00cf16e17da1e827a9de6757ec9fdc13718 /src | |
| parent | 5a5f3a980c0d2afd55f2162300339471378e341f (diff) | |
| parent | ae6fcab733007b4d59b5b2aac1825bf1f275b0b2 (diff) | |
| download | rust-36ecbc94eb6be90bc38b2d0fdd4bfac3f34d9923.tar.gz rust-36ecbc94eb6be90bc38b2d0fdd4bfac3f34d9923.zip | |
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`
Diffstat (limited to 'src')
3 files changed, 94 insertions, 12 deletions
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 184ffa85c40..bdb7a1ec92b 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -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) { diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 8b1003b5514..51991fc6039 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -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 diff --git a/src/test/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs b/src/test/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs new file mode 100644 index 00000000000..aac7d7d5385 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs @@ -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() {} |
