about summary refs log tree commit diff
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
parentd61fdbf266cf25ddf8c4798fd86e21577c8664e8 (diff)
downloadrust-a171eaab4249f70d24904da7ed392476b516a0e6.tar.gz
rust-a171eaab4249f70d24904da7ed392476b516a0e6.zip
use ty::Value instead of manual pairs of types and valtrees
-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
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/match_pair.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs9
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs29
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs5
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs41
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--tests/ui/thir-print/thir-tree-loop-match.stdout6
14 files changed, 84 insertions, 88 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;
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index dbe4ab9937f..50e8fb15cab 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -146,9 +146,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
         for arm in rest {
             let arm = &self.thir[*arm];
             let value = match arm.pattern.kind {
-                PatKind::Constant { value, .. } => value,
+                PatKind::Constant { value } => value,
                 PatKind::ExpandedConstant { ref subpattern, def_id: _ }
-                    if let PatKind::Constant { value, .. } = subpattern.kind =>
+                    if let PatKind::Constant { value } = subpattern.kind =>
                 {
                     value
                 }
@@ -160,7 +160,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
                     });
                 }
             };
-            values.push(value.unwrap_leaf().to_bits_unchecked());
+            values.push(value.try_to_scalar_int().unwrap().to_bits_unchecked());
             targets.push(self.parse_block(arm.body)?);
         }
 
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 14a237af94e..7a848536d0e 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -146,7 +146,7 @@ impl<'tcx> MatchPairTree<'tcx> {
                 }
             }
 
-            PatKind::Constant { ty, value } => Some(TestCase::Constant { ty, value }),
+            PatKind::Constant { value } => Some(TestCase::Constant { value }),
 
             PatKind::AscribeUserType {
                 ascription: Ascription { ref annotation, variance },
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 99c3611fb8a..cdbac050734 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -1245,7 +1245,7 @@ struct Ascription<'tcx> {
 #[derive(Debug, Clone)]
 enum TestCase<'tcx> {
     Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
-    Constant { ty: Ty<'tcx>, value: ty::ValTree<'tcx> },
+    Constant { value: ty::Value<'tcx> },
     Range(Arc<PatRange<'tcx>>),
     Slice { len: usize, variable_length: bool },
     Deref { temp: Place<'tcx>, mutability: Mutability },
@@ -1318,8 +1318,7 @@ enum TestKind<'tcx> {
     /// Test for equality with value, possibly after an unsizing coercion to
     /// `ty`,
     Eq {
-        value: ty::ValTree<'tcx>,
-        value_ty: Ty<'tcx>,
+        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 `f*`.
@@ -1359,7 +1358,7 @@ enum TestBranch<'tcx> {
     /// Success branch, used for tests with two possible outcomes.
     Success,
     /// Branch corresponding to this constant.
-    Constant(ty::ValTree<'tcx>, u128),
+    Constant(ty::Value<'tcx>, u128),
     /// Branch corresponding to this variant.
     Variant(VariantIdx),
     /// Failure branch for tests with two possible outcomes, and "otherwise" branch for other tests.
@@ -1367,7 +1366,7 @@ enum TestBranch<'tcx> {
 }
 
 impl<'tcx> TestBranch<'tcx> {
-    fn as_constant(&self) -> Option<ty::ValTree<'tcx>> {
+    fn as_constant(&self) -> Option<ty::Value<'tcx>> {
         if let Self::Constant(v, _) = self { Some(*v) } else { None }
     }
 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index 6ccaafc1f35..6771470e45a 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -35,9 +35,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             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, ty: value_ty } => {
-                TestKind::Eq { value, value_ty, cast_ty: match_pair.pattern_ty }
-            }
+            TestCase::Constant { value } => TestKind::Eq { value, cast_ty: match_pair.pattern_ty },
 
             TestCase::Range(ref range) => {
                 assert_eq!(range.ty, match_pair.pattern_ty);
@@ -137,14 +135,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.terminate(block, self.source_info(match_start_span), terminator);
             }
 
-            TestKind::Eq { value, value_ty, mut cast_ty } => {
+            TestKind::Eq { value, mut cast_ty } => {
                 let tcx = self.tcx;
                 let success_block = target_block(TestBranch::Success);
                 let fail_block = target_block(TestBranch::Failure);
 
-                let mut expect_ty = value_ty;
-                let value = Const::Ty(value_ty, ty::Const::new_value(tcx, value, value_ty));
-                let mut expect = self.literal_operand(test.span, value);
+                let mut expect_ty = value.ty;
+                let mut expect = self.literal_operand(test.span, Const::from_ty_value(tcx, value));
 
                 let mut place = place;
                 let mut block = block;
@@ -201,7 +198,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         cast_ty = ref_str_ty;
                     }
                     &ty::Pat(base, _) => {
-                        assert_eq!(cast_ty, value_ty);
+                        assert_eq!(cast_ty, value.ty);
                         assert!(base.is_trivially_pure_clone_copy());
 
                         let transmuted_place = self.temp(base, test.span);
@@ -282,8 +279,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
 
                 if let Some(lo) = range.lo.as_finite() {
-                    let lo = Const::Ty(range.ty, ty::Const::new_value(self.tcx, lo, range.ty));
-                    let lo = self.literal_operand(test.span, lo);
+                    let lo = self.literal_operand(test.span, Const::from_ty_value(self.tcx, lo));
                     self.compare(
                         block,
                         intermediate_block,
@@ -296,8 +292,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
 
                 if let Some(hi) = range.hi.as_finite() {
-                    let hi = Const::Ty(range.ty, ty::Const::new_value(self.tcx, hi, range.ty));
-                    let hi = self.literal_operand(test.span, hi);
+                    let hi = self.literal_operand(test.span, Const::from_ty_value(self.tcx, hi));
                     let op = match range.end {
                         RangeEnd::Included => BinOp::Le,
                         RangeEnd::Excluded => BinOp::Lt,
@@ -553,7 +548,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             //
             // FIXME(#29623) we could use PatKind::Range to rule
             // things out here, in some cases.
-            (TestKind::SwitchInt, &TestCase::Constant { value, .. })
+            (TestKind::SwitchInt, &TestCase::Constant { value })
                 if is_switch_ty(match_pair.pattern_ty) =>
             {
                 // An important invariant of candidate sorting is that a candidate
@@ -580,7 +575,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     None
                 } else {
                     fully_matched = true;
-                    let bits = value.unwrap_leaf().to_bits_unchecked();
+                    let bits = value.try_to_scalar_int().unwrap().to_bits_unchecked();
                     Some(TestBranch::Constant(value, bits))
                 }
             }
@@ -602,9 +597,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 })
             }
 
-            (TestKind::If, TestCase::Constant { value, .. }) => {
+            (TestKind::If, TestCase::Constant { value }) => {
                 fully_matched = true;
-                let value = value.unwrap_leaf().try_to_bool().unwrap_or_else(|_| {
+                let value = value.try_to_bool().unwrap_or_else(|| {
                     span_bug!(test.span, "expected boolean value but got {value:?}")
                 });
                 Some(if value { TestBranch::Success } else { TestBranch::Failure })
@@ -687,7 +682,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), &TestCase::Constant { value }) => {
                 fully_matched = false;
                 if !range.contains(value, self.tcx)? {
                     // `value` is not contained in the testing range,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index c1e9da3925e..d46c4678bcf 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -288,12 +288,12 @@ impl<'tcx> ConstToPat<'tcx> {
                 // when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
                 // This works because `str` and `&str` have the same valtree representation.
                 let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
-                PatKind::Constant { ty: ref_str_ty, value: cv }
+                PatKind::Constant { value: ty::Value { ty: ref_str_ty, valtree: cv } }
             }
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.
-                ty::Str => PatKind::Constant { ty, value: cv },
+                ty::Str => PatKind::Constant { value: ty::Value { ty, valtree: cv } },
                 // All other references are converted into deref patterns and then recursively
                 // convert the dereferenced constant to a pattern that is the sub-pattern of the
                 // deref pattern.
@@ -322,13 +322,13 @@ impl<'tcx> ConstToPat<'tcx> {
                     // Also see <https://github.com/rust-lang/rfcs/pull/3535>.
                     return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
                 } else {
-                    PatKind::Constant { ty, value: cv }
+                    PatKind::Constant { value: ty::Value { ty, valtree: cv } }
                 }
             }
             ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
                 // The raw pointers we see here have been "vetted" by valtree construction to be
                 // just integers, so we simply allow them.
-                PatKind::Constant { ty, value: cv }
+                PatKind::Constant { value: ty::Value { ty, valtree: cv } }
             }
             ty::FnPtr(..) => {
                 unreachable!(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 3a4e33b59d7..539ebc3a3d7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -156,12 +156,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         }
 
         // The unpeeled kind should now be a constant, giving us the endpoint value.
-        let PatKind::Constant { ty, value } = kind else {
+        let PatKind::Constant { value } = kind else {
             let msg =
                 format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
             return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
         };
-        Ok(Some(PatRangeBoundary::Finite(ty, value)))
+        Ok(Some(PatRangeBoundary::Finite(value)))
     }
 
     /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
@@ -243,7 +243,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             (RangeEnd::Included, Some(Ordering::Less)) => {}
             // `x..=y` where `x == y` and `x` and `y` are finite.
             (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
-                kind = PatKind::Constant { ty, value: lo.as_finite().unwrap() };
+                kind = PatKind::Constant { value: lo.as_finite().unwrap() };
             }
             // `..=x` where `x == ty::MIN`.
             (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index e5ee60150a7..b7e8d6fea40 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -761,10 +761,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_pat(subpattern, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
-            PatKind::Constant { value, ty } => {
+            PatKind::Constant { value } => {
                 print_indented!(self, "Constant {", depth_lvl + 1);
-                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
-                print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
+                print_indented!(self, format!("value: {}", value), depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
             PatKind::ExpandedConstant { def_id, subpattern } => {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 26574c5fcfc..1cc68f7f1da 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -429,8 +429,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     ) -> MaybeInfiniteInt {
         match bdy {
             PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
-            PatRangeBoundary::Finite(_ty, value) => {
-                let bits = value.unwrap_leaf().to_bits_unchecked();
+            PatRangeBoundary::Finite(value) => {
+                let bits = value.try_to_scalar_int().unwrap().to_bits_unchecked();
                 match *ty.kind() {
                     ty::Int(ity) => {
                         let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
@@ -517,16 +517,16 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     ),
                 }
             }
-            PatKind::Constant { ty: value_ty, value } => {
+            PatKind::Constant { value } => {
                 match ty.kind() {
                     ty::Bool => {
-                        ctor = Bool(value.unwrap_leaf().try_to_bool().unwrap());
+                        ctor = Bool(value.try_to_bool().unwrap());
                         fields = vec![];
                         arity = 0;
                     }
                     ty::Char | ty::Int(_) | ty::Uint(_) => {
                         ctor = {
-                            let bits = value.unwrap_leaf().to_bits_unchecked();
+                            let bits = value.try_to_scalar_int().unwrap().to_bits_unchecked();
                             let x = match *ty.kind() {
                                 ty::Int(ity) => {
                                     let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
@@ -541,7 +541,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(ty::FloatTy::F16) => {
                         use rustc_apfloat::Float;
-                        let bits = value.unwrap_leaf().to_u16();
+                        let bits = value.try_to_scalar_int().unwrap().to_u16();
                         let value = rustc_apfloat::ieee::Half::from_bits(bits.into());
                         ctor = F16Range(value, value, RangeEnd::Included);
                         fields = vec![];
@@ -549,7 +549,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(ty::FloatTy::F32) => {
                         use rustc_apfloat::Float;
-                        let bits = value.unwrap_leaf().to_u32();
+                        let bits = value.try_to_scalar_int().unwrap().to_u32();
                         let value = rustc_apfloat::ieee::Single::from_bits(bits.into());
                         ctor = F32Range(value, value, RangeEnd::Included);
                         fields = vec![];
@@ -557,7 +557,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(ty::FloatTy::F64) => {
                         use rustc_apfloat::Float;
-                        let bits = value.unwrap_leaf().to_u64();
+                        let bits = value.try_to_scalar_int().unwrap().to_u64();
                         let value = rustc_apfloat::ieee::Double::from_bits(bits.into());
                         ctor = F64Range(value, value, RangeEnd::Included);
                         fields = vec![];
@@ -565,7 +565,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(ty::FloatTy::F128) => {
                         use rustc_apfloat::Float;
-                        let bits = value.unwrap_leaf().to_u128();
+                        let bits = value.try_to_scalar_int().unwrap().to_u128();
                         let value = rustc_apfloat::ieee::Quad::from_bits(bits);
                         ctor = F128Range(value, value, RangeEnd::Included);
                         fields = vec![];
@@ -580,11 +580,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         // subfields.
                         // Note: `t` is `str`, not `&str`.
                         let ty = self.reveal_opaque_ty(*t);
-                        // FIXME: why does `Str` need a `mir::Value`?
-                        let val = mir::Const::Ty(
-                            *value_ty,
-                            ty::Const::new_value(self.tcx, *value, *value_ty),
-                        );
+                        // FIXME: why does `Str` need a `mir::Const`?
+                        let val = mir::Const::from_ty_value(self.tcx, *value);
                         let subpattern = DeconstructedPat::new(Str(val), Vec::new(), 0, ty, pat);
                         ctor = Ref;
                         fields = vec![subpattern.at_index(0)];
@@ -614,8 +611,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(fty) => {
                         use rustc_apfloat::Float;
-                        let lo = lo.as_finite().map(|c| c.unwrap_leaf().to_bits_unchecked());
-                        let hi = hi.as_finite().map(|c| c.unwrap_leaf().to_bits_unchecked());
+                        let lo = lo
+                            .as_finite()
+                            .map(|c| c.try_to_scalar_int().unwrap().to_bits_unchecked());
+                        let hi = hi
+                            .as_finite()
+                            .map(|c| c.try_to_scalar_int().unwrap().to_bits_unchecked());
                         match fty {
                             ty::FloatTy::F16 => {
                                 use rustc_apfloat::ieee::Half;
@@ -723,8 +724,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 };
                 match ScalarInt::try_from_uint(bits, size) {
                     Some(scalar) => {
-                        let value = ty::ValTree::from_scalar_int(tcx, scalar);
-                        PatRangeBoundary::Finite(ty.inner(), value)
+                        let valtree = ty::ValTree::from_scalar_int(tcx, scalar);
+                        PatRangeBoundary::Finite(ty::Value { ty: ty.inner(), valtree })
                     }
                     // The value doesn't fit. Since `x >= 0` and 0 always encodes the minimum value
                     // for a type, the problem isn't that the value is too small. So it must be too
@@ -745,7 +746,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
         } else if range.is_singleton() {
             let lo = cx.hoist_pat_range_bdy(range.lo, ty);
             let value = lo.as_finite().unwrap();
-            ty::Value { ty: ty.inner(), valtree: value }.to_string()
+            value.to_string()
         } else {
             // We convert to an inclusive range for diagnostics.
             let mut end = rustc_hir::RangeEnd::Included;
@@ -758,7 +759,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 // probably clear enough.
                 let max = ty.numeric_max_val(cx.tcx).unwrap();
                 let max = ty::ValTree::from_scalar_int(cx.tcx, max.try_to_scalar_int().unwrap());
-                lo = PatRangeBoundary::Finite(ty.inner(), max);
+                lo = PatRangeBoundary::Finite(ty::Value { ty: ty.inner(), valtree: max });
             }
             let hi = if let Some(hi) = range.hi.minus_one() {
                 hi
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 6d994a2b967..eb751da7c73 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -375,7 +375,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
         }
 
         match pat.kind {
-            thir::PatKind::Constant { value, .. } => value.has_non_region_param(),
+            thir::PatKind::Constant { value } => value.has_non_region_param(),
             thir::PatKind::Range(ref range) => {
                 let &thir::PatRange { lo, hi, .. } = range.as_ref();
                 lo.has_non_region_param() || hi.has_non_region_param()
diff --git a/tests/ui/thir-print/thir-tree-loop-match.stdout b/tests/ui/thir-print/thir-tree-loop-match.stdout
index 13d412b5737..f2b63782c59 100644
--- a/tests/ui/thir-print/thir-tree-loop-match.stdout
+++ b/tests/ui/thir-print/thir-tree-loop-match.stdout
@@ -121,8 +121,7 @@ body:
                                                                                                         span: $DIR/thir-tree-loop-match.rs:12:17: 12:21 (#0)
                                                                                                         kind: PatKind {
                                                                                                             Constant {
-                                                                                                                ty: bool
-                                                                                                                value: Leaf(0x01)
+                                                                                                                value: true
                                                                                                             }
                                                                                                         }
                                                                                                     }
@@ -220,8 +219,7 @@ body:
                                                                                                         span: $DIR/thir-tree-loop-match.rs:16:17: 16:22 (#0)
                                                                                                         kind: PatKind {
                                                                                                             Constant {
-                                                                                                                ty: bool
-                                                                                                                value: Leaf(0x00)
+                                                                                                                value: false
                                                                                                             }
                                                                                                         }
                                                                                                     }