Remove TestCase::Irrefutable

This commit is contained in:
Zalathar 2025-03-05 23:25:59 +11:00
parent ef44273838
commit 854feae887
4 changed files with 38 additions and 58 deletions

View file

@ -116,24 +116,23 @@ impl<'tcx> MatchPairTree<'tcx> {
} }
let place = place_builder.try_to_place(cx); let place = place_builder.try_to_place(cx);
let default_irrefutable = || TestCase::Irrefutable {};
let mut subpairs = Vec::new(); let mut subpairs = Vec::new();
let test_case = match pattern.kind { let test_case = match pattern.kind {
PatKind::Wild | PatKind::Error(_) => default_irrefutable(), PatKind::Wild | PatKind::Error(_) => None,
PatKind::Or { ref pats } => TestCase::Or { PatKind::Or { ref pats } => Some(TestCase::Or {
pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
}, }),
PatKind::Range(ref range) => { PatKind::Range(ref range) => {
if range.is_full_range(cx.tcx) == Some(true) { if range.is_full_range(cx.tcx) == Some(true) {
default_irrefutable() None
} else { } else {
TestCase::Range(Arc::clone(range)) Some(TestCase::Range(Arc::clone(range)))
} }
} }
PatKind::Constant { value } => TestCase::Constant { value }, PatKind::Constant { value } => Some(TestCase::Constant { value }),
PatKind::AscribeUserType { PatKind::AscribeUserType {
ascription: Ascription { ref annotation, variance }, ascription: Ascription { ref annotation, variance },
@ -154,7 +153,7 @@ impl<'tcx> MatchPairTree<'tcx> {
extra_data.ascriptions.push(super::Ascription { source, annotation, variance }); extra_data.ascriptions.push(super::Ascription { source, annotation, variance });
} }
default_irrefutable() None
} }
PatKind::Binding { mode, var, ref subpattern, .. } => { PatKind::Binding { mode, var, ref subpattern, .. } => {
@ -199,12 +198,12 @@ impl<'tcx> MatchPairTree<'tcx> {
}); });
} }
default_irrefutable() None
} }
PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => { PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
default_irrefutable() None
} }
PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => { PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
@ -233,7 +232,7 @@ impl<'tcx> MatchPairTree<'tcx> {
extra_data.ascriptions.push(super::Ascription { annotation, source, variance }); extra_data.ascriptions.push(super::Ascription { annotation, source, variance });
} }
default_irrefutable() None
} }
PatKind::Array { ref prefix, ref slice, ref suffix } => { PatKind::Array { ref prefix, ref slice, ref suffix } => {
@ -245,7 +244,7 @@ impl<'tcx> MatchPairTree<'tcx> {
slice, slice,
suffix, suffix,
); );
default_irrefutable() None
} }
PatKind::Slice { ref prefix, ref slice, ref suffix } => { PatKind::Slice { ref prefix, ref slice, ref suffix } => {
cx.prefix_slice_suffix( cx.prefix_slice_suffix(
@ -258,12 +257,12 @@ impl<'tcx> MatchPairTree<'tcx> {
); );
if prefix.is_empty() && slice.is_some() && suffix.is_empty() { if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
default_irrefutable() None
} else { } else {
TestCase::Slice { Some(TestCase::Slice {
len: prefix.len() + suffix.len(), len: prefix.len() + suffix.len(),
variable_length: slice.is_some(), variable_length: slice.is_some(),
} })
} }
} }
@ -279,16 +278,12 @@ impl<'tcx> MatchPairTree<'tcx> {
.apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env))
}) && (adt_def.did().is_local() }) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive()); || !adt_def.is_variant_list_non_exhaustive());
if irrefutable { if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) }
default_irrefutable()
} else {
TestCase::Variant { adt_def, variant_index }
}
} }
PatKind::Leaf { ref subpatterns } => { PatKind::Leaf { ref subpatterns } => {
cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns); cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns);
default_irrefutable() None
} }
PatKind::Deref { ref subpattern } => { PatKind::Deref { ref subpattern } => {
@ -299,7 +294,7 @@ impl<'tcx> MatchPairTree<'tcx> {
&mut subpairs, &mut subpairs,
extra_data, extra_data,
); );
default_irrefutable() None
} }
PatKind::DerefPattern { ref subpattern, mutability } => { PatKind::DerefPattern { ref subpattern, mutability } => {
@ -316,18 +311,25 @@ impl<'tcx> MatchPairTree<'tcx> {
&mut subpairs, &mut subpairs,
extra_data, extra_data,
); );
TestCase::Deref { temp, mutability } Some(TestCase::Deref { temp, mutability })
} }
PatKind::Never => TestCase::Never, PatKind::Never => Some(TestCase::Never),
}; };
match_pairs.push(MatchPairTree { if let Some(test_case) = test_case {
place, // This pattern is refutable, so push a new match-pair node.
test_case, match_pairs.push(MatchPairTree {
subpairs, place,
pattern_ty: pattern.ty, test_case,
pattern_span: pattern.span, subpairs,
}); pattern_ty: pattern.ty,
pattern_span: pattern.span,
})
} else {
// This pattern is irrefutable, so it doesn't need its own match-pair node.
// Just push its refutable subpatterns instead, if any.
match_pairs.extend(subpairs);
}
} }
} }

View file

@ -1054,7 +1054,6 @@ struct Candidate<'tcx> {
/// (see [`Builder::test_remaining_match_pairs_after_or`]). /// (see [`Builder::test_remaining_match_pairs_after_or`]).
/// ///
/// Invariants: /// Invariants:
/// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
/// - All or-patterns ([`TestCase::Or`]) have been sorted to the end. /// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
match_pairs: Vec<MatchPairTree<'tcx>>, match_pairs: Vec<MatchPairTree<'tcx>>,
@ -1226,17 +1225,11 @@ struct Ascription<'tcx> {
/// - [`Builder::pick_test_for_match_pair`] (to choose a test) /// - [`Builder::pick_test_for_match_pair`] (to choose a test)
/// - [`Builder::sort_candidate`] (to see how the test interacts with a match pair) /// - [`Builder::sort_candidate`] (to see how the test interacts with a match pair)
/// ///
/// Two variants are unlike the others and deserve special mention: /// Note that or-patterns are not tested directly like the other variants.
/// /// Instead they participate in or-pattern expansion, where they are transformed into
/// - [`Self::Irrefutable`] is only used temporarily when building a [`MatchPairTree`]. /// subcandidates. See [`Builder::expand_and_match_or_candidates`].
/// They are then flattened away by [`Builder::simplify_match_pairs`], with any
/// bindings/ascriptions incorporated into the enclosing [`FlatPat`].
/// - [`Self::Or`] are not tested directly like the other variants. Instead they
/// participate in or-pattern expansion, where they are transformed into subcandidates.
/// - See [`Builder::expand_and_match_or_candidates`].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum TestCase<'tcx> { enum TestCase<'tcx> {
Irrefutable {},
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx }, Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
Constant { value: mir::Const<'tcx> }, Constant { value: mir::Const<'tcx> },
Range(Arc<PatRange<'tcx>>), Range(Arc<PatRange<'tcx>>),
@ -1269,10 +1262,6 @@ pub(crate) struct MatchPairTree<'tcx> {
place: Option<Place<'tcx>>, place: Option<Place<'tcx>>,
/// ... must pass this test... /// ... must pass this test...
///
/// ---
/// Invariant: after creation and simplification in [`FlatPat::new`],
/// this must not be [`TestCase::Irrefutable`].
test_case: TestCase<'tcx>, test_case: TestCase<'tcx>,
/// ... and these subpairs must match. /// ... and these subpairs must match.

View file

@ -47,13 +47,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// match lowering forces us to lower bindings inside or-patterns last. // match lowering forces us to lower bindings inside or-patterns last.
for mut match_pair in mem::take(match_pairs) { for mut match_pair in mem::take(match_pairs) {
self.simplify_match_pairs(&mut match_pair.subpairs, extra_data); self.simplify_match_pairs(&mut match_pair.subpairs, extra_data);
if let TestCase::Irrefutable {} = match_pair.test_case { // Unsimplifiable pattern; we keep it.
// Simplifiable pattern; we replace it with its already simplified subpairs. match_pairs.push(match_pair);
match_pairs.append(&mut match_pair.subpairs);
} else {
// Unsimplifiable pattern; we keep it.
match_pairs.push(match_pair);
}
} }
// Move or-patterns to the end, because they can result in us // Move or-patterns to the end, because they can result in us

View file

@ -55,12 +55,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Or-patterns are not tested directly; instead they are expanded into subcandidates, // Or-patterns are not tested directly; instead they are expanded into subcandidates,
// which are then distinguished by testing whatever non-or patterns they contain. // which are then distinguished by testing whatever non-or patterns they contain.
TestCase::Or { .. } => bug!("or-patterns should have already been handled"), TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
TestCase::Irrefutable { .. } => span_bug!(
match_pair.pattern_span,
"simplifiable pattern found: {:?}",
match_pair.pattern_span
),
}; };
Test { span: match_pair.pattern_span, kind } Test { span: match_pair.pattern_span, kind }