1
Fork 0

Specialized Usefulness variants are redundant

This commit is contained in:
Nadrieril 2021-01-01 22:14:54 +00:00
parent 307a278d5c
commit 37e7dd22a9

View file

@ -846,15 +846,14 @@ impl<'p, 'tcx> SubPatSet<'p, 'tcx> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum Usefulness<'p, 'tcx> { enum Usefulness<'p, 'tcx> {
/// Potentially carries a set of sub-branches that have been found to be unreachable. Used /// Carries a set of subpatterns that have been found to be unreachable. If full, this
/// only in the presence of or-patterns, otherwise it stays empty. /// indicates the whole pattern is unreachable. If not, this indicates that the pattern is
/// reachable but has some unreachable sub-patterns (due to or-patterns). In the absence of
/// or-patterns, this is either `Empty` or `Full`.
NoWitnesses(SubPatSet<'p, 'tcx>), NoWitnesses(SubPatSet<'p, 'tcx>),
/// When not carrying witnesses, indicates that the whole pattern is unreachable. /// Carries a list of witnesses of non-exhaustiveness. If empty, indicates that the whole
NoWitnessesFull, /// pattern is unreachable.
/// Carries a list of witnesses of non-exhaustiveness. Non-empty.
WithWitnesses(Vec<Witness<'tcx>>), WithWitnesses(Vec<Witness<'tcx>>),
/// When carrying witnesses, indicates that the whole pattern is unreachable.
WithWitnessesEmpty,
} }
impl<'p, 'tcx> Usefulness<'p, 'tcx> { impl<'p, 'tcx> Usefulness<'p, 'tcx> {
@ -866,27 +865,19 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
} }
fn new_not_useful(preference: WitnessPreference) -> Self { fn new_not_useful(preference: WitnessPreference) -> Self {
match preference { match preference {
ConstructWitness => WithWitnessesEmpty, ConstructWitness => WithWitnesses(vec![]),
LeaveOutWitness => NoWitnessesFull, LeaveOutWitness => NoWitnesses(SubPatSet::full()),
} }
} }
/// Combine usefulnesses from two branches. This is an associative operation. /// Combine usefulnesses from two branches. This is an associative operation.
fn extend(&mut self, other: Self) { fn extend(&mut self, other: Self) {
match (&mut *self, other) { match (&mut *self, other) {
(WithWitnesses(_), WithWitnesses(o)) if o.is_empty() => {}
(WithWitnesses(s), WithWitnesses(o)) if s.is_empty() => *self = WithWitnesses(o),
(WithWitnesses(s), WithWitnesses(o)) => s.extend(o), (WithWitnesses(s), WithWitnesses(o)) => s.extend(o),
(WithWitnessesEmpty, WithWitnesses(o)) => *self = WithWitnesses(o),
(WithWitnesses(_), WithWitnessesEmpty) => {}
(WithWitnessesEmpty, WithWitnessesEmpty) => {}
(NoWitnesses(s), NoWitnesses(o)) => s.intersect(o), (NoWitnesses(s), NoWitnesses(o)) => s.intersect(o),
(NoWitnessesFull, NoWitnesses(o)) => *self = NoWitnesses(o), _ => unreachable!(),
(NoWitnesses(_), NoWitnessesFull) => {}
(NoWitnessesFull, NoWitnessesFull) => {}
_ => {
unreachable!()
}
} }
} }
@ -909,12 +900,10 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
/// After calculating the usefulness for a branch of an or-pattern, call this to make this /// After calculating the usefulness for a branch of an or-pattern, call this to make this
/// usefulness mergeable with those from the other branches. /// usefulness mergeable with those from the other branches.
fn unsplit_or_pat(self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>) -> Self { fn unsplit_or_pat(self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>) -> Self {
let subpats = match self { match self {
NoWitnesses(subpats) => subpats, NoWitnesses(subpats) => NoWitnesses(subpats.unsplit_or_pat(alt_id, alt_count, pat)),
NoWitnessesFull => SubPatSet::full(), WithWitnesses(_) => bug!(),
WithWitnesses(_) | WithWitnessesEmpty => bug!(), }
};
NoWitnesses(subpats.unsplit_or_pat(alt_id, alt_count, pat))
} }
/// After calculating usefulness after a specialization, call this to recontruct a usefulness /// After calculating usefulness after a specialization, call this to recontruct a usefulness
@ -928,6 +917,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
ctor_wild_subpatterns: &Fields<'p, 'tcx>, ctor_wild_subpatterns: &Fields<'p, 'tcx>,
) -> Self { ) -> Self {
match self { match self {
WithWitnesses(witnesses) if witnesses.is_empty() => WithWitnesses(witnesses),
WithWitnesses(witnesses) => { WithWitnesses(witnesses) => {
let new_witnesses = if matches!(ctor, Constructor::Missing) { let new_witnesses = if matches!(ctor, Constructor::Missing) {
let mut split_wildcard = SplitWildcard::new(pcx); let mut split_wildcard = SplitWildcard::new(pcx);
@ -961,8 +951,6 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
WithWitnesses(new_witnesses) WithWitnesses(new_witnesses)
} }
NoWitnesses(subpats) => NoWitnesses(subpats.unspecialize(ctor_wild_subpatterns.len())), NoWitnesses(subpats) => NoWitnesses(subpats.unspecialize(ctor_wild_subpatterns.len())),
NoWitnessesFull => NoWitnessesFull,
WithWitnessesEmpty => WithWitnessesEmpty,
} }
} }
} }
@ -1209,8 +1197,7 @@ crate fn compute_match_usefulness<'p, 'tcx>(
let reachability = match usefulness { let reachability = match usefulness {
NoWitnesses(subpats) if subpats.is_full() => Reachability::Unreachable, NoWitnesses(subpats) if subpats.is_full() => Reachability::Unreachable,
NoWitnesses(subpats) => Reachability::Reachable(subpats.to_spans().unwrap()), NoWitnesses(subpats) => Reachability::Reachable(subpats.to_spans().unwrap()),
NoWitnessesFull => Reachability::Unreachable, WithWitnesses(..) => bug!(),
WithWitnesses(..) | WithWitnessesEmpty => bug!(),
}; };
(arm, reachability) (arm, reachability)
}) })
@ -1220,15 +1207,8 @@ crate fn compute_match_usefulness<'p, 'tcx>(
let v = PatStack::from_pattern(wild_pattern); let v = PatStack::from_pattern(wild_pattern);
let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true); let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
let non_exhaustiveness_witnesses = match usefulness { let non_exhaustiveness_witnesses = match usefulness {
WithWitnessesEmpty => vec![], // Wildcard pattern isn't useful, so the match is exhaustive. WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
WithWitnesses(pats) => { NoWitnesses(_) => bug!(),
if pats.is_empty() {
bug!("Exhaustiveness check returned no witnesses")
} else {
pats.into_iter().map(|w| w.single_pattern()).collect()
}
}
NoWitnesses(_) | NoWitnessesFull => bug!(),
}; };
UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses } UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
} }