From 23ed79bc006b2fb9ec3fd5d59edf4150078ce8fd Mon Sep 17 00:00:00 2001
From: FedericoBruzzone <federico.bruzzone.i@gmail.com>
Date: Mon, 27 Jan 2025 09:14:51 +0100
Subject: [PATCH] Move `try_to_bits` from `Const` to `Valtree`

Signed-off-by: FedericoBruzzone <federico.bruzzone.i@gmail.com>
---
 .../src/debuginfo/type_names.rs               | 10 +++---
 compiler/rustc_middle/src/ty/consts.rs        | 12 -------
 .../rustc_middle/src/ty/consts/valtree.rs     | 15 +++++++++
 .../src/cfi/typeid/itanium_cxx_abi/encode.rs  | 10 +++---
 compiler/rustc_symbol_mangling/src/v0.rs      |  4 +--
 compiler/rustc_ty_utils/src/layout.rs         | 31 ++++++++++++-------
 6 files changed, 45 insertions(+), 37 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 869798d8be194..3dc9758554bdb 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -676,17 +676,15 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
         ty::ConstKind::Value(ty, valtree) => {
             match ty.kind() {
                 ty::Int(ity) => {
-                    // FIXME: directly extract the bits from a valtree instead of evaluating an
-                    // already evaluated `Const` in order to get the bits.
-                    let bits = ct
-                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
+                    let bits = valtree
+                        .try_to_bits(tcx, ty, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in codegen");
                     let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
                     write!(output, "{val}")
                 }
                 ty::Uint(_) => {
-                    let val = ct
-                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
+                    let val = valtree
+                        .try_to_bits(tcx, ty, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in codegen");
                     write!(output, "{val}")
                 }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 310552764224e..7c340bd4b6ba6 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -245,18 +245,6 @@ impl<'tcx> Const<'tcx> {
         self.try_to_valtree()?.0.try_to_target_usize(tcx)
     }
 
-    /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
-    /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
-    /// contains const generic parameters or pointers).
-    #[inline]
-    pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
-        let (scalar, ty) = self.try_to_scalar()?;
-        let scalar = scalar.try_to_scalar_int().ok()?;
-        let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
-        let size = tcx.layout_of(input).ok()?.size;
-        Some(scalar.to_bits(size))
-    }
-
     pub fn is_ct_infer(self) -> bool {
         matches!(self.kind(), ty::ConstKind::Infer(_))
     }
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 9f9bf41c3355a..2f246a0e245e8 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -83,6 +83,21 @@ impl<'tcx> ValTree<'tcx> {
         self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
     }
 
+    /// Attempts to extract the raw bits of the valtree.
+    /// 
+    /// Can fail if the value can't be represented as bits (e.g. because it is an aggregate).
+    pub fn try_to_bits(
+        self,
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+    ) -> Option<u128> {
+        let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
+        let size = tcx.layout_of(input).ok()?.size;
+        let scalar = self.try_to_scalar_int()?;
+        Some(scalar.to_bits(size))
+    }
+
     /// Get the values inside the ValTree as a slice of bytes. This only works for
     /// constants with types &str, &[u8], or [u8; _].
     pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 09648e28df471..7b6defd884ba0 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -121,7 +121,7 @@ fn encode_const<'tcx>(
         }
 
         // Literal arguments
-        ty::ConstKind::Value(ct_ty, ..) => {
+        ty::ConstKind::Value(ct_ty, valtree) => {
             // L<element-type>[n]<element-value>E as literal argument
 
             // Element type
@@ -132,8 +132,8 @@ fn encode_const<'tcx>(
             // bool value false is encoded as 0 and true as 1.
             match ct_ty.kind() {
                 ty::Int(ity) => {
-                    let bits = c
-                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
+                    let bits = valtree
+                        .try_to_bits(tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in cfi");
                     let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
@@ -142,8 +142,8 @@ fn encode_const<'tcx>(
                     let _ = write!(s, "{val}");
                 }
                 ty::Uint(_) => {
-                    let val = c
-                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
+                    let val = valtree
+                        .try_to_bits(tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in cfi");
                     let _ = write!(s, "{val}");
                 }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 4ddf530a00d4a..d25d938d6c4b3 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -625,8 +625,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
                 ct_ty.print(self)?;
 
-                let mut bits = ct
-                    .try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized())
+                let mut bits = valtree
+                    .try_to_bits(self.tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
                     .expect("expected const to be monomorphic");
 
                 // Negative integer values are mangled using `n` as a "sign prefix".
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index a04c753611831..fde9a634d401d 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -33,6 +33,12 @@ use crate::errors::{
 
 mod invariant;
 
+/// The `ValTree` alongside its type.
+struct ValTreeAndTy<'tcx> {
+    valtree: ty::ValTree<'tcx>,
+    ty: Ty<'tcx>,
+}
+
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { layout_of, ..*providers };
 }
@@ -144,13 +150,13 @@ fn univariant_uninterned<'tcx>(
     cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
 }
 
-fn validate_const_with_value<'tcx>(
+fn extract_valtree_and_ty<'tcx>(
     const_: ty::Const<'tcx>,
     ty: Ty<'tcx>,
     cx: &LayoutCx<'tcx>,
-) -> Result<ty::Const<'tcx>, &'tcx LayoutError<'tcx>> {
+) -> Result<ValTreeAndTy<'tcx>, &'tcx LayoutError<'tcx>> {
     match const_.kind() {
-        ty::ConstKind::Value(..) => Ok(const_),
+        ty::ConstKind::Value(ty, valtree) => Ok(ValTreeAndTy { valtree, ty }),
         ty::ConstKind::Error(guar) => {
             return Err(error(cx, LayoutError::ReferencesError(guar)));
         }
@@ -209,14 +215,16 @@ fn layout_of_uncached<'tcx>(
                         &mut layout.backend_repr
                     {
                         if let Some(start) = start {
-                            scalar.valid_range_mut().start =
-                                validate_const_with_value(start, ty, cx)?
-                                    .try_to_bits(tcx, cx.typing_env)
-                                    .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
+                            let ValTreeAndTy { valtree, ty } =
+                                extract_valtree_and_ty(start, ty, cx)?;
+                            scalar.valid_range_mut().start = valtree
+                                .try_to_bits(tcx, ty, cx.typing_env)
+                                .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                         }
                         if let Some(end) = end {
-                            let mut end = validate_const_with_value(end, ty, cx)?
-                                .try_to_bits(tcx, cx.typing_env)
+                            let ValTreeAndTy { valtree, ty } = extract_valtree_and_ty(end, ty, cx)?;
+                            let mut end = valtree
+                                .try_to_bits(tcx, ty, cx.typing_env)
                                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                             if !include_end {
                                 end = end.wrapping_sub(1);
@@ -348,9 +356,8 @@ fn layout_of_uncached<'tcx>(
 
         // Arrays and slices.
         ty::Array(element, count) => {
-            let count = validate_const_with_value(count, ty, cx)?
-                .to_valtree()
-                .0
+            let count = extract_valtree_and_ty(count, ty, cx)?
+                .valtree
                 .try_to_target_usize(tcx)
                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;