Rename TestCase to TestableCase
This commit is contained in:
parent
6e7dd2cd99
commit
7f6f522761
5 changed files with 64 additions and 54 deletions
|
|
@ -7,7 +7,7 @@ use tracing::debug;
|
|||
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::matches::test::is_switch_ty;
|
||||
use crate::builder::matches::{Candidate, Test, TestBranch, TestCase, TestKind};
|
||||
use crate::builder::matches::{Candidate, Test, TestBranch, TestKind, TestableCase};
|
||||
|
||||
/// Output of [`Builder::partition_candidates_into_buckets`].
|
||||
pub(crate) struct PartitionedCandidates<'tcx, 'b, 'c> {
|
||||
|
|
@ -140,12 +140,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// branch, so it can be removed. If false, the match pair is _compatible_
|
||||
// with its test branch, but still needs a more specific test.
|
||||
let fully_matched;
|
||||
let ret = match (&test.kind, &match_pair.test_case) {
|
||||
let ret = match (&test.kind, &match_pair.testable_case) {
|
||||
// If we are performing a variant switch, then this
|
||||
// informs variant patterns, but nothing else.
|
||||
(
|
||||
&TestKind::Switch { adt_def: tested_adt_def },
|
||||
&TestCase::Variant { adt_def, variant_index },
|
||||
&TestableCase::Variant { adt_def, variant_index },
|
||||
) => {
|
||||
assert_eq!(adt_def, tested_adt_def);
|
||||
fully_matched = true;
|
||||
|
|
@ -159,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// things out here, in some cases.
|
||||
//
|
||||
// FIXME(Zalathar): Is the `is_switch_ty` test unnecessary?
|
||||
(TestKind::SwitchInt, &TestCase::Constant { value })
|
||||
(TestKind::SwitchInt, &TestableCase::Constant { value })
|
||||
if is_switch_ty(match_pair.pattern_ty) =>
|
||||
{
|
||||
// An important invariant of candidate bucketing is that a candidate
|
||||
|
|
@ -167,16 +167,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// a new value might invalidate that property for range patterns that
|
||||
// have already been partitioned into the failure arm, so we must take care
|
||||
// not to add such values here.
|
||||
let is_covering_range = |test_case: &TestCase<'tcx>| {
|
||||
test_case.as_range().is_some_and(|range| {
|
||||
let is_covering_range = |testable_case: &TestableCase<'tcx>| {
|
||||
testable_case.as_range().is_some_and(|range| {
|
||||
matches!(range.contains(value, self.tcx), None | Some(true))
|
||||
})
|
||||
};
|
||||
let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| {
|
||||
candidate
|
||||
.match_pairs
|
||||
.iter()
|
||||
.any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
|
||||
candidate.match_pairs.iter().any(|mp| {
|
||||
mp.place == Some(test_place) && is_covering_range(&mp.testable_case)
|
||||
})
|
||||
};
|
||||
if prior_candidates
|
||||
.get(&TestBranch::Failure)
|
||||
|
|
@ -189,7 +188,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
Some(TestBranch::Constant(value))
|
||||
}
|
||||
}
|
||||
(TestKind::SwitchInt, TestCase::Range(range)) => {
|
||||
(TestKind::SwitchInt, TestableCase::Range(range)) => {
|
||||
// When performing a `SwitchInt` test, a range pattern can be
|
||||
// sorted into the failure arm if it doesn't contain _any_ of
|
||||
// the values being tested. (This restricts what values can be
|
||||
|
|
@ -207,7 +206,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
(TestKind::If, TestCase::Constant { value }) => {
|
||||
(TestKind::If, TestableCase::Constant { value }) => {
|
||||
fully_matched = true;
|
||||
let value = value.try_to_bool().unwrap_or_else(|| {
|
||||
span_bug!(test.span, "expected boolean value but got {value:?}")
|
||||
|
|
@ -217,7 +216,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
(
|
||||
&TestKind::Len { len: test_len, op: BinOp::Eq },
|
||||
&TestCase::Slice { len, variable_length },
|
||||
&TestableCase::Slice { len, variable_length },
|
||||
) => {
|
||||
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||
(Ordering::Equal, false) => {
|
||||
|
|
@ -249,7 +248,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
(
|
||||
&TestKind::Len { len: test_len, op: BinOp::Ge },
|
||||
&TestCase::Slice { len, variable_length },
|
||||
&TestableCase::Slice { len, variable_length },
|
||||
) => {
|
||||
// the test is `$actual_len >= test_len`
|
||||
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||
|
|
@ -281,7 +280,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
(TestKind::Range(test), TestCase::Range(pat)) => {
|
||||
(TestKind::Range(test), TestableCase::Range(pat)) => {
|
||||
if test == pat {
|
||||
fully_matched = true;
|
||||
Some(TestBranch::Success)
|
||||
|
|
@ -292,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
if !test.overlaps(pat, self.tcx)? { Some(TestBranch::Failure) } else { None }
|
||||
}
|
||||
}
|
||||
(TestKind::Range(range), &TestCase::Constant { value }) => {
|
||||
(TestKind::Range(range), &TestableCase::Constant { value }) => {
|
||||
fully_matched = false;
|
||||
if !range.contains(value, self.tcx)? {
|
||||
// `value` is not contained in the testing range,
|
||||
|
|
@ -303,7 +302,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
(TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val }) => {
|
||||
(TestKind::Eq { value: test_val, .. }, TestableCase::Constant { value: case_val }) => {
|
||||
if test_val == case_val {
|
||||
fully_matched = true;
|
||||
Some(TestBranch::Success)
|
||||
|
|
@ -313,7 +312,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
(TestKind::Deref { temp: test_temp, .. }, TestCase::Deref { temp, .. })
|
||||
(TestKind::Deref { temp: test_temp, .. }, TestableCase::Deref { temp, .. })
|
||||
if test_temp == temp =>
|
||||
{
|
||||
fully_matched = true;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt};
|
|||
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
|
||||
use crate::builder::matches::{FlatPat, MatchPairTree, PatternExtraData, TestCase};
|
||||
use crate::builder::matches::{FlatPat, MatchPairTree, PatternExtraData, TestableCase};
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in
|
||||
|
|
@ -132,7 +132,7 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
|
||||
let place = place_builder.try_to_place(cx);
|
||||
let mut subpairs = Vec::new();
|
||||
let test_case = match pattern.kind {
|
||||
let testable_case = match pattern.kind {
|
||||
PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None,
|
||||
|
||||
PatKind::Or { ref pats } => {
|
||||
|
|
@ -146,18 +146,18 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
// FIXME(@dianne): this needs updating/removing if we always merge or-patterns
|
||||
extra_data.bindings.push(super::SubpatternBindings::FromOrPattern);
|
||||
}
|
||||
Some(TestCase::Or { pats })
|
||||
Some(TestableCase::Or { pats })
|
||||
}
|
||||
|
||||
PatKind::Range(ref range) => {
|
||||
if range.is_full_range(cx.tcx) == Some(true) {
|
||||
None
|
||||
} else {
|
||||
Some(TestCase::Range(Arc::clone(range)))
|
||||
Some(TestableCase::Range(Arc::clone(range)))
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Constant { value } => Some(TestCase::Constant { value }),
|
||||
PatKind::Constant { value } => Some(TestableCase::Constant { value }),
|
||||
|
||||
PatKind::AscribeUserType {
|
||||
ascription: Ascription { ref annotation, variance },
|
||||
|
|
@ -256,7 +256,7 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(TestCase::Slice {
|
||||
Some(TestableCase::Slice {
|
||||
len: prefix.len() + suffix.len(),
|
||||
variable_length: slice.is_some(),
|
||||
})
|
||||
|
|
@ -275,7 +275,11 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
cx.def_id.into(),
|
||||
)
|
||||
}) && !adt_def.variant_list_has_applicable_non_exhaustive();
|
||||
if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) }
|
||||
if irrefutable {
|
||||
None
|
||||
} else {
|
||||
Some(TestableCase::Variant { adt_def, variant_index })
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
|
|
@ -331,17 +335,17 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
&mut subpairs,
|
||||
extra_data,
|
||||
);
|
||||
Some(TestCase::Deref { temp, mutability })
|
||||
Some(TestableCase::Deref { temp, mutability })
|
||||
}
|
||||
|
||||
PatKind::Never => Some(TestCase::Never),
|
||||
PatKind::Never => Some(TestableCase::Never),
|
||||
};
|
||||
|
||||
if let Some(test_case) = test_case {
|
||||
if let Some(testable_case) = testable_case {
|
||||
// This pattern is refutable, so push a new match-pair node.
|
||||
match_pairs.push(MatchPairTree {
|
||||
place,
|
||||
test_case,
|
||||
testable_case,
|
||||
subpairs,
|
||||
pattern_ty: pattern.ty,
|
||||
pattern_span: pattern.span,
|
||||
|
|
|
|||
|
|
@ -1078,7 +1078,7 @@ struct Candidate<'tcx> {
|
|||
/// (see [`Builder::test_remaining_match_pairs_after_or`]).
|
||||
///
|
||||
/// Invariants:
|
||||
/// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
|
||||
/// - All or-patterns ([`TestableCase::Or`]) have been sorted to the end.
|
||||
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||
|
||||
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
||||
|
|
@ -1164,12 +1164,15 @@ impl<'tcx> Candidate<'tcx> {
|
|||
|
||||
/// Restores the invariant that or-patterns must be sorted to the end.
|
||||
fn sort_match_pairs(&mut self) {
|
||||
self.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
||||
self.match_pairs.sort_by_key(|pair| matches!(pair.testable_case, TestableCase::Or { .. }));
|
||||
}
|
||||
|
||||
/// Returns whether the first match pair of this candidate is an or-pattern.
|
||||
fn starts_with_or_pattern(&self) -> bool {
|
||||
matches!(&*self.match_pairs, [MatchPairTree { test_case: TestCase::Or { .. }, .. }, ..])
|
||||
matches!(
|
||||
&*self.match_pairs,
|
||||
[MatchPairTree { testable_case: TestableCase::Or { .. }, .. }, ..]
|
||||
)
|
||||
}
|
||||
|
||||
/// Visit the leaf candidates (those with no subcandidates) contained in
|
||||
|
|
@ -1261,7 +1264,7 @@ struct Ascription<'tcx> {
|
|||
/// Instead they participate in or-pattern expansion, where they are transformed into
|
||||
/// subcandidates. See [`Builder::expand_and_match_or_candidates`].
|
||||
#[derive(Debug, Clone)]
|
||||
enum TestCase<'tcx> {
|
||||
enum TestableCase<'tcx> {
|
||||
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
|
||||
Constant { value: ty::Value<'tcx> },
|
||||
Range(Arc<PatRange<'tcx>>),
|
||||
|
|
@ -1271,7 +1274,7 @@ enum TestCase<'tcx> {
|
|||
Or { pats: Box<[FlatPat<'tcx>]> },
|
||||
}
|
||||
|
||||
impl<'tcx> TestCase<'tcx> {
|
||||
impl<'tcx> TestableCase<'tcx> {
|
||||
fn as_range(&self) -> Option<&PatRange<'tcx>> {
|
||||
if let Self::Range(v) = self { Some(v.as_ref()) } else { None }
|
||||
}
|
||||
|
|
@ -1289,12 +1292,12 @@ pub(crate) struct MatchPairTree<'tcx> {
|
|||
/// ---
|
||||
/// This can be `None` if it referred to a non-captured place in a closure.
|
||||
///
|
||||
/// Invariant: Can only be `None` when `test_case` is `Or`.
|
||||
/// Invariant: Can only be `None` when `testable_case` is `Or`.
|
||||
/// Therefore this must be `Some(_)` after or-pattern expansion.
|
||||
place: Option<Place<'tcx>>,
|
||||
|
||||
/// ... must pass this test...
|
||||
test_case: TestCase<'tcx>,
|
||||
testable_case: TestableCase<'tcx>,
|
||||
|
||||
/// ... and these subpairs must match.
|
||||
///
|
||||
|
|
@ -1317,7 +1320,7 @@ enum TestKind<'tcx> {
|
|||
/// Test what enum variant a value is.
|
||||
///
|
||||
/// The subset of expected variants is not stored here; instead they are
|
||||
/// extracted from the [`TestCase`]s of the candidates participating in the
|
||||
/// extracted from the [`TestableCase`]s of the candidates participating in the
|
||||
/// test.
|
||||
Switch {
|
||||
/// The enum type being tested.
|
||||
|
|
@ -1327,7 +1330,7 @@ enum TestKind<'tcx> {
|
|||
/// Test what value an integer or `char` has.
|
||||
///
|
||||
/// The test's target values are not stored here; instead they are extracted
|
||||
/// from the [`TestCase`]s of the candidates participating in the test.
|
||||
/// from the [`TestableCase`]s of the candidates participating in the test.
|
||||
SwitchInt,
|
||||
|
||||
/// Test whether a `bool` is `true` or `false`.
|
||||
|
|
@ -1948,7 +1951,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
candidate: &mut Candidate<'tcx>,
|
||||
match_pair: MatchPairTree<'tcx>,
|
||||
) {
|
||||
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
||||
let TestableCase::Or { pats } = match_pair.testable_case else { bug!() };
|
||||
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
||||
candidate.or_span = Some(match_pair.pattern_span);
|
||||
candidate.subcandidates = pats
|
||||
|
|
@ -2116,7 +2119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
debug_assert!(
|
||||
remaining_match_pairs
|
||||
.iter()
|
||||
.all(|match_pair| matches!(match_pair.test_case, TestCase::Or { .. }))
|
||||
.all(|match_pair| matches!(match_pair.testable_case, TestableCase::Or { .. }))
|
||||
);
|
||||
|
||||
// Visit each leaf candidate within this subtree, add a copy of the remaining
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::matches::{MatchPairTree, Test, TestBranch, TestCase, TestKind};
|
||||
use crate::builder::matches::{MatchPairTree, Test, TestBranch, TestKind, TestableCase};
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
||||
|
|
@ -29,30 +29,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&mut self,
|
||||
match_pair: &MatchPairTree<'tcx>,
|
||||
) -> Test<'tcx> {
|
||||
let kind = match match_pair.test_case {
|
||||
TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
|
||||
let kind = match match_pair.testable_case {
|
||||
TestableCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
|
||||
|
||||
TestCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
|
||||
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => TestKind::SwitchInt,
|
||||
TestCase::Constant { value } => TestKind::Eq { value, cast_ty: match_pair.pattern_ty },
|
||||
TestableCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
|
||||
TestableCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => {
|
||||
TestKind::SwitchInt
|
||||
}
|
||||
TestableCase::Constant { value } => {
|
||||
TestKind::Eq { value, cast_ty: match_pair.pattern_ty }
|
||||
}
|
||||
|
||||
TestCase::Range(ref range) => {
|
||||
TestableCase::Range(ref range) => {
|
||||
assert_eq!(range.ty, match_pair.pattern_ty);
|
||||
TestKind::Range(Arc::clone(range))
|
||||
}
|
||||
|
||||
TestCase::Slice { len, variable_length } => {
|
||||
TestableCase::Slice { len, variable_length } => {
|
||||
let op = if variable_length { BinOp::Ge } else { BinOp::Eq };
|
||||
TestKind::Len { len: len as u64, op }
|
||||
}
|
||||
|
||||
TestCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
|
||||
TestableCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
|
||||
|
||||
TestCase::Never => TestKind::Never,
|
||||
TestableCase::Never => TestKind::Never,
|
||||
|
||||
// Or-patterns are not tested directly; instead they are expanded into subcandidates,
|
||||
// which are then distinguished by testing whatever non-or patterns they contain.
|
||||
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||
TestableCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||
};
|
||||
|
||||
Test { span: match_pair.pattern_span, kind }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use tracing::debug;
|
|||
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::expr::as_place::PlaceBase;
|
||||
use crate::builder::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestCase};
|
||||
use crate::builder::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestableCase};
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Creates a false edge to `imaginary_target` and a real edge to
|
||||
|
|
@ -159,11 +159,11 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) {
|
||||
if let TestCase::Or { pats, .. } = &match_pair.test_case {
|
||||
if let TestableCase::Or { pats, .. } = &match_pair.testable_case {
|
||||
for flat_pat in pats.iter() {
|
||||
self.visit_flat_pat(flat_pat)
|
||||
}
|
||||
} else if matches!(match_pair.test_case, TestCase::Deref { .. }) {
|
||||
} else if matches!(match_pair.testable_case, TestableCase::Deref { .. }) {
|
||||
// The subpairs of a deref pattern are all places relative to the deref temporary, so we
|
||||
// don't fake borrow them. Problem is, if we only shallowly fake-borrowed
|
||||
// `match_pair.place`, this would allow:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue