Skip to content

Commit 293af41

Browse files
committed
Split Usefulness::NotUseful into two
1 parent f4f20c0 commit 293af41

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

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

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -680,24 +680,32 @@ impl SpanSet {
680680

681681
#[derive(Clone, Debug)]
682682
enum Usefulness<'tcx> {
683-
/// Pontentially carries a set of sub-branches that have been found to be unreachable. Used
683+
/// Potentially carries a set of sub-branches that have been found to be unreachable. Used
684684
/// only in the presence of or-patterns, otherwise it stays empty.
685-
Useful(SpanSet),
686-
/// Carries a list of witnesses of non-exhaustiveness.
687-
UsefulWithWitness(Vec<Witness<'tcx>>),
688-
NotUseful,
685+
NoWitnesses(SpanSet),
686+
/// When not carrying witnesses, indicates that the whole pattern is unreachable.
687+
NoWitnessesFull,
688+
/// Carries a list of witnesses of non-exhaustiveness. Non-empty.
689+
WithWitnesses(Vec<Witness<'tcx>>),
690+
/// When carrying witnesses, indicates that the whole pattern is unreachable.
691+
WithWitnessesEmpty,
689692
}
690693

691694
impl<'tcx> Usefulness<'tcx> {
692695
fn new_useful(preference: WitnessPreference) -> Self {
693696
match preference {
694-
ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
695-
LeaveOutWitness => Useful(Default::default()),
697+
ConstructWitness => WithWitnesses(vec![Witness(vec![])]),
698+
LeaveOutWitness => NoWitnesses(Default::default()),
699+
}
700+
}
701+
fn new_not_useful(preference: WitnessPreference) -> Self {
702+
match preference {
703+
ConstructWitness => WithWitnessesEmpty,
704+
LeaveOutWitness => NoWitnessesFull,
696705
}
697706
}
698707

699-
/// Combine usefulnesses from two branches. This is an associative operation and `NotUseful` is
700-
/// a unit.
708+
/// Combine usefulnesses from two branches. This is an associative operation.
701709
fn extend(&mut self, other: Self) {
702710
// If we have detected some unreachable sub-branches, we only want to keep them when they
703711
// were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
@@ -720,21 +728,29 @@ impl<'tcx> Usefulness<'tcx> {
720728
// }
721729
// ```
722730
match (&mut *self, other) {
723-
(Useful(s), Useful(o)) => s.intersection_mut(&o),
724-
(UsefulWithWitness(s), UsefulWithWitness(o)) => s.extend(o),
725-
(_, NotUseful) => {}
726-
(NotUseful, other) => *self = other,
727-
(UsefulWithWitness(_), Useful(_)) | (Useful(_), UsefulWithWitness(_)) => unreachable!(),
731+
(WithWitnesses(s), WithWitnesses(o)) => s.extend(o),
732+
(WithWitnessesEmpty, WithWitnesses(o)) => *self = WithWitnesses(o),
733+
(WithWitnesses(_), WithWitnessesEmpty) => {}
734+
(WithWitnessesEmpty, WithWitnessesEmpty) => {}
735+
736+
(NoWitnesses(s), NoWitnesses(o)) => s.intersection_mut(&o),
737+
(NoWitnessesFull, NoWitnesses(o)) => *self = NoWitnesses(o),
738+
(NoWitnesses(_), NoWitnessesFull) => {}
739+
(NoWitnessesFull, NoWitnessesFull) => {}
740+
741+
_ => {
742+
unreachable!()
743+
}
728744
}
729745
}
730746

731747
/// When trying several branches and each returns a `Usefulness`, we need to combine the
732748
/// results together.
733-
fn merge(usefulnesses: impl Iterator<Item = Self>) -> Self {
734-
let mut ret = NotUseful;
749+
fn merge(pref: WitnessPreference, usefulnesses: impl Iterator<Item = Self>) -> Self {
750+
let mut ret = Self::new_not_useful(pref);
735751
for u in usefulnesses {
736752
ret.extend(u);
737-
if let Useful(spans) = &ret {
753+
if let NoWitnesses(spans) = &ret {
738754
if spans.is_empty() {
739755
// Once we reach the empty set, more intersections won't change the result.
740756
return ret;
@@ -748,7 +764,7 @@ impl<'tcx> Usefulness<'tcx> {
748764
/// usefulness mergeable with those from the other branches.
749765
fn unsplit_or_pat(self, this_span: Span, or_pat_spans: &[Span]) -> Self {
750766
match self {
751-
Useful(mut spans) => {
767+
NoWitnesses(mut spans) => {
752768
// We register the spans of the other branches of this or-pattern as being
753769
// unreachable from this one. This ensures that intersecting together the sets of
754770
// spans returns what we want.
@@ -759,9 +775,10 @@ impl<'tcx> Usefulness<'tcx> {
759775
spans.push_nonintersecting(span);
760776
}
761777
}
762-
Useful(spans)
778+
NoWitnesses(spans)
763779
}
764-
x => x,
780+
NoWitnessesFull => NoWitnessesFull,
781+
WithWitnesses(_) | WithWitnessesEmpty => bug!(),
765782
}
766783
}
767784

@@ -776,7 +793,7 @@ impl<'tcx> Usefulness<'tcx> {
776793
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
777794
) -> Self {
778795
match self {
779-
UsefulWithWitness(witnesses) => {
796+
WithWitnesses(witnesses) => {
780797
let new_witnesses = if matches!(ctor, Constructor::Missing) {
781798
let mut split_wildcard = SplitWildcard::new(pcx);
782799
split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
@@ -806,7 +823,7 @@ impl<'tcx> Usefulness<'tcx> {
806823
.map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
807824
.collect()
808825
};
809-
UsefulWithWitness(new_witnesses)
826+
WithWitnesses(new_witnesses)
810827
}
811828
x => x,
812829
}
@@ -935,8 +952,11 @@ fn is_useful<'p, 'tcx>(
935952
// first and then, if v is non-empty, the return value is based on whether
936953
// the type of the tuple we're checking is inhabited or not.
937954
if v.is_empty() {
938-
let ret =
939-
if rows.is_empty() { Usefulness::new_useful(witness_preference) } else { NotUseful };
955+
let ret = if rows.is_empty() {
956+
Usefulness::new_useful(witness_preference)
957+
} else {
958+
Usefulness::new_not_useful(witness_preference)
959+
};
940960
debug!(?ret);
941961
return ret;
942962
}
@@ -966,7 +986,7 @@ fn is_useful<'p, 'tcx>(
966986
}
967987
usefulness.unsplit_or_pat(v_span, &subspans)
968988
});
969-
Usefulness::merge(usefulnesses)
989+
Usefulness::merge(witness_preference, usefulnesses)
970990
} else {
971991
let v_ctor = v.head_ctor(cx);
972992
if let Constructor::IntRange(ctor_range) = &v_ctor {
@@ -994,7 +1014,7 @@ fn is_useful<'p, 'tcx>(
9941014
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
9951015
usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
9961016
});
997-
Usefulness::merge(usefulnesses)
1017+
Usefulness::merge(witness_preference, usefulnesses)
9981018
};
9991019
debug!(?ret);
10001020
ret
@@ -1049,9 +1069,9 @@ crate fn compute_match_usefulness<'p, 'tcx>(
10491069
matrix.push(v);
10501070
}
10511071
let reachability = match usefulness {
1052-
Useful(spans) => Reachability::Reachable(spans),
1053-
NotUseful => Reachability::Unreachable,
1054-
UsefulWithWitness(..) => bug!(),
1072+
NoWitnesses(spans) => Reachability::Reachable(spans),
1073+
NoWitnessesFull => Reachability::Unreachable,
1074+
WithWitnesses(..) | WithWitnessesEmpty => bug!(),
10551075
};
10561076
(arm, reachability)
10571077
})
@@ -1061,15 +1081,15 @@ crate fn compute_match_usefulness<'p, 'tcx>(
10611081
let v = PatStack::from_pattern(wild_pattern);
10621082
let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
10631083
let non_exhaustiveness_witnesses = match usefulness {
1064-
NotUseful => vec![], // Wildcard pattern isn't useful, so the match is exhaustive.
1065-
UsefulWithWitness(pats) => {
1084+
WithWitnessesEmpty => vec![], // Wildcard pattern isn't useful, so the match is exhaustive.
1085+
WithWitnesses(pats) => {
10661086
if pats.is_empty() {
10671087
bug!("Exhaustiveness check returned no witnesses")
10681088
} else {
10691089
pats.into_iter().map(|w| w.single_pattern()).collect()
10701090
}
10711091
}
1072-
Useful(_) => bug!(),
1092+
NoWitnesses(_) | NoWitnessesFull => bug!(),
10731093
};
10741094
UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
10751095
}

0 commit comments

Comments
 (0)