about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-07-29 08:54:34 +0200
committerRalf Jung <post@ralfj.de>2025-08-14 09:44:22 +0200
commita171eaab4249f70d24904da7ed392476b516a0e6 (patch)
tree711de138a04a38b498c41b2d4ea777c38e892a1a /compiler/rustc_middle
parentd61fdbf266cf25ddf8c4798fd86e21577c8664e8 (diff)
downloadrust-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.rs5
-rw-r--r--compiler/rustc_middle/src/thir.rs37
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs14
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;