Skip to content

Commit 6319d73

Browse files
committed
Merge unreachable subpatterns correctly
1 parent 2d71a0b commit 6319d73

File tree

3 files changed

+36
-19
lines changed

3 files changed

+36
-19
lines changed

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -788,13 +788,32 @@ impl<'tcx> Usefulness<'tcx> {
788788
/// When trying several branches and each returns a `Usefulness`, we need to combine the
789789
/// results together.
790790
fn merge_split_constructors(usefulnesses: impl Iterator<Item = Self>) -> Self {
791+
// If we have detected some unreachable sub-branches, we only want to keep them when they
792+
// were unreachable in _all_ branches. So we take a big intersection.
793+
794+
// Is `None` when no branch was useful. Will often be `Some(Spanset::new())` because the
795+
// sets are only non-empty in the diagnostic path.
796+
let mut unreachables: Option<SpanSet> = None;
791797
// Witnesses of usefulness, if any.
792798
let mut witnesses = Vec::new();
793799

794800
for u in usefulnesses {
795801
match u {
796-
Useful(..) => {
797-
return u;
802+
Useful(spans) if spans.is_empty() => {
803+
// Once we reach the empty set, more intersections won't change the result.
804+
return Useful(SpanSet::new());
805+
}
806+
Useful(spans) => {
807+
if let Some(unreachables) = &mut unreachables {
808+
if !unreachables.is_empty() {
809+
unreachables.intersection_mut(&spans);
810+
}
811+
if unreachables.is_empty() {
812+
return Useful(SpanSet::new());
813+
}
814+
} else {
815+
unreachables = Some(spans);
816+
}
798817
}
799818
NotUseful => {}
800819
UsefulWithWitness(wits) => {
@@ -803,7 +822,13 @@ impl<'tcx> Usefulness<'tcx> {
803822
}
804823
}
805824

806-
if !witnesses.is_empty() { UsefulWithWitness(witnesses) } else { NotUseful }
825+
if !witnesses.is_empty() {
826+
UsefulWithWitness(witnesses)
827+
} else if let Some(unreachables) = unreachables {
828+
Useful(unreachables)
829+
} else {
830+
NotUseful
831+
}
807832
}
808833

809834
fn apply_constructor<'p>(

src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,9 @@ fn main() {
6464
| 2, ..] => {}
6565
_ => {}
6666
}
67-
// FIXME: incorrect
6867
match &[][..] {
6968
[true] => {}
70-
[true //~ ERROR unreachable
71-
| false, ..] => {}
69+
[true | false, ..] => {}
7270
_ => {}
7371
}
7472
match &[][..] {

src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr

+7-13
Original file line numberDiff line numberDiff line change
@@ -95,46 +95,40 @@ LL | [1
9595
| ^
9696

9797
error: unreachable pattern
98-
--> $DIR/exhaustiveness-unreachable-pattern.rs:70:10
98+
--> $DIR/exhaustiveness-unreachable-pattern.rs:75:10
9999
|
100100
LL | [true
101101
| ^^^^
102102

103103
error: unreachable pattern
104-
--> $DIR/exhaustiveness-unreachable-pattern.rs:77:10
105-
|
106-
LL | [true
107-
| ^^^^
108-
109-
error: unreachable pattern
110-
--> $DIR/exhaustiveness-unreachable-pattern.rs:84:36
104+
--> $DIR/exhaustiveness-unreachable-pattern.rs:82:36
111105
|
112106
LL | (true | false, None | Some(true
113107
| ^^^^
114108

115109
error: unreachable pattern
116-
--> $DIR/exhaustiveness-unreachable-pattern.rs:100:14
110+
--> $DIR/exhaustiveness-unreachable-pattern.rs:98:14
117111
|
118112
LL | Some(0
119113
| ^
120114

121115
error: unreachable pattern
122-
--> $DIR/exhaustiveness-unreachable-pattern.rs:119:19
116+
--> $DIR/exhaustiveness-unreachable-pattern.rs:117:19
123117
|
124118
LL | | false) => {}
125119
| ^^^^^
126120

127121
error: unreachable pattern
128-
--> $DIR/exhaustiveness-unreachable-pattern.rs:127:15
122+
--> $DIR/exhaustiveness-unreachable-pattern.rs:125:15
129123
|
130124
LL | | true) => {}
131125
| ^^^^
132126

133127
error: unreachable pattern
134-
--> $DIR/exhaustiveness-unreachable-pattern.rs:133:15
128+
--> $DIR/exhaustiveness-unreachable-pattern.rs:131:15
135129
|
136130
LL | | true,
137131
| ^^^^
138132

139-
error: aborting due to 22 previous errors
133+
error: aborting due to 21 previous errors
140134

0 commit comments

Comments
 (0)