Skip to content

Commit

Permalink
Merge unreachable subpatterns correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Dec 18, 2020
1 parent 2d71a0b commit 6319d73
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
31 changes: 28 additions & 3 deletions compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
Expand Up @@ -788,13 +788,32 @@ impl<'tcx> Usefulness<'tcx> {
/// When trying several branches and each returns a `Usefulness`, we need to combine the
/// results together.
fn merge_split_constructors(usefulnesses: impl Iterator<Item = Self>) -> Self {
// If we have detected some unreachable sub-branches, we only want to keep them when they
// were unreachable in _all_ branches. So we take a big intersection.

// Is `None` when no branch was useful. Will often be `Some(Spanset::new())` because the
// sets are only non-empty in the diagnostic path.
let mut unreachables: Option<SpanSet> = None;
// Witnesses of usefulness, if any.
let mut witnesses = Vec::new();

for u in usefulnesses {
match u {
Useful(..) => {
return u;
Useful(spans) if spans.is_empty() => {
// Once we reach the empty set, more intersections won't change the result.
return Useful(SpanSet::new());
}
Useful(spans) => {
if let Some(unreachables) = &mut unreachables {
if !unreachables.is_empty() {
unreachables.intersection_mut(&spans);
}
if unreachables.is_empty() {
return Useful(SpanSet::new());
}
} else {
unreachables = Some(spans);
}
}
NotUseful => {}
UsefulWithWitness(wits) => {
Expand All @@ -803,7 +822,13 @@ impl<'tcx> Usefulness<'tcx> {
}
}

if !witnesses.is_empty() { UsefulWithWitness(witnesses) } else { NotUseful }
if !witnesses.is_empty() {
UsefulWithWitness(witnesses)
} else if let Some(unreachables) = unreachables {
Useful(unreachables)
} else {
NotUseful
}
}

fn apply_constructor<'p>(
Expand Down
Expand Up @@ -64,11 +64,9 @@ fn main() {
| 2, ..] => {}
_ => {}
}
// FIXME: incorrect
match &[][..] {
[true] => {}
[true //~ ERROR unreachable
| false, ..] => {}
[true | false, ..] => {}
_ => {}
}
match &[][..] {
Expand Down
20 changes: 7 additions & 13 deletions src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
Expand Up @@ -95,46 +95,40 @@ LL | [1
| ^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:70:10
--> $DIR/exhaustiveness-unreachable-pattern.rs:75:10
|
LL | [true
| ^^^^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:77:10
|
LL | [true
| ^^^^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:84:36
--> $DIR/exhaustiveness-unreachable-pattern.rs:82:36
|
LL | (true | false, None | Some(true
| ^^^^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:100:14
--> $DIR/exhaustiveness-unreachable-pattern.rs:98:14
|
LL | Some(0
| ^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:119:19
--> $DIR/exhaustiveness-unreachable-pattern.rs:117:19
|
LL | | false) => {}
| ^^^^^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:127:15
--> $DIR/exhaustiveness-unreachable-pattern.rs:125:15
|
LL | | true) => {}
| ^^^^

error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:133:15
--> $DIR/exhaustiveness-unreachable-pattern.rs:131:15
|
LL | | true,
| ^^^^

error: aborting due to 22 previous errors
error: aborting due to 21 previous errors

0 comments on commit 6319d73

Please sign in to comment.