Split out a separate PatConstKind::String
This commit is contained in:
parent
91e169b1c9
commit
3c7c439812
5 changed files with 47 additions and 16 deletions
|
|
@ -1218,6 +1218,12 @@ impl<'tcx> Ty<'tcx> {
|
|||
*self.kind() == Str
|
||||
}
|
||||
|
||||
/// Returns true if this type is `&str`. The reference's lifetime is ignored.
|
||||
#[inline]
|
||||
pub fn is_imm_ref_str(self) -> bool {
|
||||
matches!(self.kind(), ty::Ref(_, inner, hir::Mutability::Not) if inner.is_str())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_param(self, index: u32) -> bool {
|
||||
match self.kind() {
|
||||
|
|
|
|||
|
|
@ -314,7 +314,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
(
|
||||
TestKind::Eq { value: test_val, .. },
|
||||
TestKind::StringEq { value: test_val, .. },
|
||||
TestableCase::Constant { value: case_val, kind: PatConstKind::String },
|
||||
)
|
||||
| (
|
||||
TestKind::ScalarEq { value: test_val, .. },
|
||||
TestableCase::Constant {
|
||||
value: case_val,
|
||||
kind: PatConstKind::Float | PatConstKind::Other,
|
||||
|
|
@ -347,7 +351,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| TestKind::If
|
||||
| TestKind::SliceLen { .. }
|
||||
| TestKind::Range { .. }
|
||||
| TestKind::Eq { .. }
|
||||
| TestKind::StringEq { .. }
|
||||
| TestKind::ScalarEq { .. }
|
||||
| TestKind::Deref { .. },
|
||||
_,
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::sync::Arc;
|
|||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
|
||||
|
|
@ -173,9 +174,21 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
PatConstKind::IntOrChar
|
||||
} else if pat_ty.is_floating_point() {
|
||||
PatConstKind::Float
|
||||
} else if pat_ty.is_str() {
|
||||
// Deref-patterns can cause string-literal patterns to have
|
||||
// type `str` instead of the usual `&str`.
|
||||
if !cx.tcx.features().deref_patterns() {
|
||||
span_bug!(
|
||||
pattern.span,
|
||||
"const pattern has type `str` but deref_patterns is not enabled"
|
||||
);
|
||||
}
|
||||
PatConstKind::String
|
||||
} else if pat_ty.is_imm_ref_str() {
|
||||
PatConstKind::String
|
||||
} else {
|
||||
// FIXME(Zalathar): This still covers several different
|
||||
// categories (e.g. raw pointer, string, pattern-type)
|
||||
// categories (e.g. raw pointer, pattern-type)
|
||||
// which could be split out into their own kinds.
|
||||
PatConstKind::Other
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1290,9 +1290,10 @@ enum PatConstKind {
|
|||
/// These types don't support `SwitchInt` and require an equality test,
|
||||
/// but can also interact with range pattern tests.
|
||||
Float,
|
||||
/// Constant string values, tested via string equality.
|
||||
String,
|
||||
/// Any other constant-pattern is usually tested via some kind of equality
|
||||
/// check. Types that might be encountered here include:
|
||||
/// - `&str`
|
||||
/// - raw pointers derived from integer values
|
||||
/// - pattern types, e.g. `pattern_type!(u32 is 1..)`
|
||||
Other,
|
||||
|
|
@ -1368,14 +1369,20 @@ enum TestKind<'tcx> {
|
|||
/// Test whether a `bool` is `true` or `false`.
|
||||
If,
|
||||
|
||||
/// Test for equality with value, possibly after an unsizing coercion to
|
||||
/// `cast_ty`,
|
||||
Eq {
|
||||
/// Tests the place against a string constant using string equality.
|
||||
StringEq {
|
||||
/// Constant `&str` value to test against.
|
||||
value: ty::Value<'tcx>,
|
||||
// Integer types are handled by `SwitchInt`, and constants with ADT
|
||||
// types and `&[T]` types are converted back into patterns, so this can
|
||||
// only be `&str` or floats.
|
||||
cast_ty: Ty<'tcx>,
|
||||
/// Type of the corresponding pattern node. Usually `&str`, but could
|
||||
/// be `str` for patterns like `deref!("..."): String`.
|
||||
pat_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
/// Tests the place against a constant using scalar equality.
|
||||
ScalarEq {
|
||||
value: ty::Value<'tcx>,
|
||||
/// Type of the corresponding pattern node.
|
||||
pat_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
/// Test whether the value falls within an inclusive or exclusive range.
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
TestableCase::Constant { value: _, kind: PatConstKind::IntOrChar } => {
|
||||
TestKind::SwitchInt
|
||||
}
|
||||
TestableCase::Constant { value, kind: PatConstKind::Float } => {
|
||||
TestKind::Eq { value, cast_ty: match_pair.pattern_ty }
|
||||
TestableCase::Constant { value, kind: PatConstKind::String } => {
|
||||
TestKind::StringEq { value, pat_ty: match_pair.pattern_ty }
|
||||
}
|
||||
TestableCase::Constant { value, kind: PatConstKind::Other } => {
|
||||
TestKind::Eq { value, cast_ty: match_pair.pattern_ty }
|
||||
TestableCase::Constant { value, kind: PatConstKind::Float | PatConstKind::Other } => {
|
||||
TestKind::ScalarEq { value, pat_ty: match_pair.pattern_ty }
|
||||
}
|
||||
|
||||
TestableCase::Range(ref range) => {
|
||||
|
|
@ -141,7 +141,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.cfg.terminate(block, self.source_info(match_start_span), terminator);
|
||||
}
|
||||
|
||||
TestKind::Eq { value, cast_ty: pat_ty } => {
|
||||
TestKind::StringEq { value, pat_ty } | TestKind::ScalarEq { value, pat_ty } => {
|
||||
let tcx = self.tcx;
|
||||
let success_block = target_block(TestBranch::Success);
|
||||
let fail_block = target_block(TestBranch::Failure);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue