diff options
| author | Ralf Jung <post@ralfj.de> | 2025-07-29 08:54:34 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-08-14 09:44:22 +0200 |
| commit | a171eaab4249f70d24904da7ed392476b516a0e6 (patch) | |
| tree | 711de138a04a38b498c41b2d4ea777c38e892a1a /compiler/rustc_middle | |
| parent | d61fdbf266cf25ddf8c4798fd86e21577c8664e8 (diff) | |
| download | rust-a171eaab4249f70d24904da7ed392476b516a0e6.tar.gz rust-a171eaab4249f70d24904da7ed392476b516a0e6.zip | |
use ty::Value instead of manual pairs of types and valtrees
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/consts.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/thir.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/thir/visit.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts/valtree.rs | 14 |
4 files changed, 31 insertions, 27 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 96131d47a17..164433aede2 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -448,6 +448,11 @@ impl<'tcx> Const<'tcx> { Self::Val(val, ty) } + #[inline] + pub fn from_ty_value(tcx: TyCtxt<'tcx>, val: ty::Value<'tcx>) -> Self { + Self::Ty(val.ty, ty::Const::new_value(tcx, val.valtree, val.ty)) + } + pub fn from_bits( tcx: TyCtxt<'tcx>, bits: u128, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 62f76671b78..4910aa93be8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -842,10 +842,7 @@ pub enum PatKind<'tcx> { // error. /// * `String`, if `string_deref_patterns` is enabled. Constant { - // Not using `ty::Value` since this is conceptually not a type-level constant. In - // particular, it can have raw pointers. - ty: Ty<'tcx>, - value: ty::ValTree<'tcx>, + value: ty::Value<'tcx>, }, /// Pattern obtained by converting a constant (inline or named) to its pattern @@ -937,8 +934,8 @@ impl<'tcx> PatRange<'tcx> { // Also, for performance, it's important to only do the second `try_to_bits` if necessary. let lo_is_min = match self.lo { PatRangeBoundary::NegInfinity => true, - PatRangeBoundary::Finite(_ty, value) => { - let lo = value.unwrap_leaf().to_bits(size) ^ bias; + PatRangeBoundary::Finite(value) => { + let lo = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias; lo <= min } PatRangeBoundary::PosInfinity => false, @@ -946,8 +943,8 @@ impl<'tcx> PatRange<'tcx> { if lo_is_min { let hi_is_max = match self.hi { PatRangeBoundary::NegInfinity => false, - PatRangeBoundary::Finite(_ty, value) => { - let hi = value.unwrap_leaf().to_bits(size) ^ bias; + PatRangeBoundary::Finite(value) => { + let hi = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias; hi > max || hi == max && self.end == RangeEnd::Included } PatRangeBoundary::PosInfinity => true, @@ -960,10 +957,11 @@ impl<'tcx> PatRange<'tcx> { } #[inline] - pub fn contains(&self, value: ty::ValTree<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> { + pub fn contains(&self, value: ty::Value<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> { use Ordering::*; + debug_assert_eq!(self.ty, value.ty); let ty = self.ty; - let value = PatRangeBoundary::Finite(ty, value); + let value = PatRangeBoundary::Finite(value); // For performance, it's important to only do the second comparison if necessary. Some( match self.lo.compare_with(value, ty, tcx)? { @@ -998,13 +996,10 @@ impl<'tcx> PatRange<'tcx> { impl<'tcx> fmt::Display for PatRange<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let &PatRangeBoundary::Finite(ty, value) = &self.lo { - // `ty::Value` has a reasonable pretty-printing implementation. - let value = ty::Value { ty, valtree: value }; + if let PatRangeBoundary::Finite(value) = &self.lo { write!(f, "{value}")?; } - if let &PatRangeBoundary::Finite(ty, value) = &self.hi { - let value = ty::Value { ty, valtree: value }; + if let PatRangeBoundary::Finite(value) = &self.hi { write!(f, "{}", self.end)?; write!(f, "{value}")?; } else { @@ -1019,7 +1014,7 @@ impl<'tcx> fmt::Display for PatRange<'tcx> { /// If present, the const must be of a numeric type. #[derive(Copy, Clone, Debug, PartialEq, HashStable, TypeVisitable)] pub enum PatRangeBoundary<'tcx> { - Finite(Ty<'tcx>, ty::ValTree<'tcx>), + Finite(ty::Value<'tcx>), NegInfinity, PosInfinity, } @@ -1030,15 +1025,15 @@ impl<'tcx> PatRangeBoundary<'tcx> { matches!(self, Self::Finite(..)) } #[inline] - pub fn as_finite(self) -> Option<ty::ValTree<'tcx>> { + pub fn as_finite(self) -> Option<ty::Value<'tcx>> { match self { - Self::Finite(_ty, value) => Some(value), + Self::Finite(value) => Some(value), Self::NegInfinity | Self::PosInfinity => None, } } pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> u128 { match self { - Self::Finite(_ty, value) => value.unwrap_leaf().to_bits_unchecked(), + Self::Finite(value) => value.try_to_scalar_int().unwrap().to_bits_unchecked(), Self::NegInfinity => { // Unwrap is ok because the type is known to be numeric. ty.numeric_min_and_max_as_bits(tcx).unwrap().0 @@ -1065,9 +1060,7 @@ impl<'tcx> PatRangeBoundary<'tcx> { // we can do scalar comparisons. E.g. `unicode-normalization` has // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared // in this way. - (Finite(_, a), Finite(_, b)) - if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => - { + (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => { if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) { let sz = ty.primitive_size(tcx); let cmp = match ty.kind() { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 9d3ba74ad0f..dcfa6c4db32 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -265,7 +265,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( PatKind::Missing | PatKind::Wild | PatKind::Binding { subpattern: None, .. } - | PatKind::Constant { .. } + | PatKind::Constant { value: _ } | PatKind::Range(_) | PatKind::Never | PatKind::Error(_) => {} diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 002a86a8897..0f6f3f0c0e2 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -135,6 +135,8 @@ pub type ConstToValTreeResult<'tcx> = Result<Result<ValTree<'tcx>, Ty<'tcx>>, Er /// A type-level constant value. /// /// Represents a typed, fully evaluated constant. +/// Note that this is used by pattern elaboration to represent values which cannot occur in types, +/// such as raw pointers and floats. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable, Lift)] pub struct Value<'tcx> { @@ -149,15 +151,19 @@ impl<'tcx> Value<'tcx> { /// or an aggregate). #[inline] pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> { - let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else { - return None; - }; - let scalar = self.valtree.try_to_scalar_int()?; + let scalar = self.try_to_scalar_int()?; let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty); let size = tcx.layout_of(input).ok()?.size; Some(scalar.to_bits(size)) } + pub fn try_to_scalar_int(self) -> Option<ScalarInt> { + let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else { + return None; + }; + self.valtree.try_to_scalar_int() + } + pub fn try_to_bool(self) -> Option<bool> { if !self.ty.is_bool() { return None; |
