about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-02-03 21:11:35 +0100
committerGitHub <noreply@github.com>2025-02-03 21:11:35 +0100
commit7e0118cdd257b886a94efa83234c6f400973894e (patch)
treebac3a04a5f2002871f34f1e2ab0ea84b088d391a
parent2c6c7f8ef2029712e82c96ecd614973faf537bd1 (diff)
parent00c61a81a0c6685d3d5470d5111eeb0159911836 (diff)
downloadrust-7e0118cdd257b886a94efa83234c6f400973894e.tar.gz
rust-7e0118cdd257b886a94efa83234c6f400973894e.zip
Rollup merge of #136430 - FedericoBruzzone:follow-up-136180, r=oli-obk
Use the type-level constant value `ty::Value` where needed

**Follow-up to #136180**

### Summary

This PR refactors functions to accept a single type-level constant value `ty::Value` instead of separate `ty::ValTree` and `ty::Ty` parameters:

- `valtree_to_const_value`: now takes `ty::Value`
- `pretty_print_const_valtree`: now takes `ty::Value`
- Uses `pretty_print_const_valtree` for formatting valtrees  when `visit_const_operand`
- Moves `try_to_raw_bytes` from `ty::Valtree` to `ty::Value`

---

r? ``@lukas-code`` ``@oli-obk``
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs42
-rw-r--r--compiler/rustc_const_eval/src/lib.rs10
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs11
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs47
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs42
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
7 files changed, 79 insertions, 78 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 4d625f76aba..c35910a706b 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -273,59 +273,63 @@ pub(crate) fn eval_to_valtree<'tcx>(
 /// Converts a `ValTree` to a `ConstValue`, which is needed after mir
 /// construction has finished.
 // FIXME(valtrees): Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
-// FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
 #[instrument(skip(tcx), level = "debug", ret)]
 pub fn valtree_to_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
-    ty: Ty<'tcx>,
-    valtree: ty::ValTree<'tcx>,
+    cv: ty::Value<'tcx>,
 ) -> mir::ConstValue<'tcx> {
     // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
     // (those for constants with type bool, int, uint, float or char).
     // For all other types we create an `MPlace` and fill that by walking
     // the `ValTree` and using `place_projection` and `place_field` to
     // create inner `MPlace`s which are filled recursively.
-    // FIXME Does this need an example?
-    match *ty.kind() {
+    // FIXME: Does this need an example?
+    match *cv.ty.kind() {
         ty::FnDef(..) => {
-            assert!(valtree.unwrap_branch().is_empty());
+            assert!(cv.valtree.unwrap_branch().is_empty());
             mir::ConstValue::ZeroSized
         }
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_, _) => {
-            match valtree {
+            match cv.valtree {
                 ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)),
                 ty::ValTree::Branch(_) => bug!(
                     "ValTrees for Bool, Int, Uint, Float, Char or RawPtr should have the form ValTree::Leaf"
                 ),
             }
         }
-        ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree),
+        ty::Pat(ty, _) => {
+            let cv = ty::Value { valtree: cv.valtree, ty };
+            valtree_to_const_value(tcx, typing_env, cv)
+        }
         ty::Ref(_, inner_ty, _) => {
             let mut ecx =
                 mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
-            let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
-            let imm =
-                ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
+            let imm = valtree_to_ref(&mut ecx, cv.valtree, inner_ty);
+            let imm = ImmTy::from_immediate(
+                imm,
+                tcx.layout_of(typing_env.as_query_input(cv.ty)).unwrap(),
+            );
             op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
         }
         ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
-            let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
+            let layout = tcx.layout_of(typing_env.as_query_input(cv.ty)).unwrap();
             if layout.is_zst() {
                 // Fast path to avoid some allocations.
                 return mir::ConstValue::ZeroSized;
             }
             if layout.backend_repr.is_scalar()
-                && (matches!(ty.kind(), ty::Tuple(_))
-                    || matches!(ty.kind(), ty::Adt(def, _) if def.is_struct()))
+                && (matches!(cv.ty.kind(), ty::Tuple(_))
+                    || matches!(cv.ty.kind(), ty::Adt(def, _) if def.is_struct()))
             {
                 // A Scalar tuple/struct; we can avoid creating an allocation.
-                let branches = valtree.unwrap_branch();
+                let branches = cv.valtree.unwrap_branch();
                 // Find the non-ZST field. (There can be aligned ZST!)
                 for (i, &inner_valtree) in branches.iter().enumerate() {
                     let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
                     if !field.is_zst() {
-                        return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree);
+                        let cv = ty::Value { valtree: inner_valtree, ty: field.ty };
+                        return valtree_to_const_value(tcx, typing_env, cv);
                     }
                 }
                 bug!("could not find non-ZST field during in {layout:#?}");
@@ -335,9 +339,9 @@ pub fn valtree_to_const_value<'tcx>(
                 mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
 
             // Need to create a place for this valtree.
-            let place = create_valtree_place(&mut ecx, layout, valtree);
+            let place = create_valtree_place(&mut ecx, layout, cv.valtree);
 
-            valtree_into_mplace(&mut ecx, &place, valtree);
+            valtree_into_mplace(&mut ecx, &place, cv.valtree);
             dump_place(&ecx, &place);
             intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap();
 
@@ -362,7 +366,7 @@ pub fn valtree_to_const_value<'tcx>(
         | ty::Slice(_)
         | ty::Dynamic(..)
         | ty::UnsafeBinder(_) => {
-            bug!("no ValTree should have been created for type {:?}", ty.kind())
+            bug!("no ValTree should have been created for type {:?}", cv.ty.kind())
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index ecf9745b779..b44d2a01d57 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -46,14 +46,8 @@ pub fn provide(providers: &mut Providers) {
     };
     providers.hooks.try_destructure_mir_constant_for_user_output =
         const_eval::try_destructure_mir_constant_for_user_output;
-    providers.valtree_to_const_val = |tcx, cv| {
-        const_eval::valtree_to_const_value(
-            tcx,
-            ty::TypingEnv::fully_monomorphized(),
-            cv.ty,
-            cv.valtree,
-        )
-    };
+    providers.valtree_to_const_val =
+        |tcx, cv| const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), cv);
     providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 09d7e60e199..aa8ec3aff04 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use tracing::trace;
+use ty::print::PrettyPrinter;
 
 use super::graphviz::write_mir_fn_graphviz;
 use crate::mir::interpret::ConstAllocation;
@@ -1439,10 +1440,10 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                 })
             };
 
-            // FIXME: call pretty_print_const_valtree?
-            let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
-                ty::ValTree::Leaf(leaf) => format!("Leaf({leaf:?})"),
-                ty::ValTree::Branch(_) => "Branch(..)".to_string(),
+            let fmt_valtree = |cv: &ty::Value<'tcx>| {
+                let mut cx = FmtPrinter::new(self.tcx, Namespace::ValueNS);
+                cx.pretty_print_const_valtree(*cv, /*print_ty*/ true).unwrap();
+                cx.into_buffer()
             };
 
             let val = match const_ {
@@ -1452,7 +1453,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                         format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
                     }
                     ty::ConstKind::Value(cv) => {
-                        format!("ty::Valtree({})", fmt_valtree(&cv.valtree))
+                        format!("ty::Valtree({})", fmt_valtree(&cv))
                     }
                     // No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
                     ty::ConstKind::Error(_) => "Error".to_string(),
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index d914b7576dc..5905076c4d0 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -78,30 +78,6 @@ impl<'tcx> ValTree<'tcx> {
             Self::Branch(_) => None,
         }
     }
-
-    /// 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]> {
-        match ty.kind() {
-            ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
-                // `&str` can be interpreted as raw bytes
-                ty::Str => {}
-                // `&[u8]` can be interpreted as raw bytes
-                ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {}
-                // other `&_` can't be interpreted as raw bytes
-                _ => return None,
-            },
-            // `[u8; N]` can be interpreted as raw bytes
-            ty::Array(array_ty, _) if *array_ty == tcx.types.u8 => {}
-            // Otherwise, type cannot be interpreted as raw bytes
-            _ => return None,
-        }
-
-        Some(
-            tcx.arena
-                .alloc_from_iter(self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8())),
-        )
-    }
 }
 
 /// A type-level constant value.
@@ -143,6 +119,29 @@ impl<'tcx> Value<'tcx> {
         }
         self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
     }
+
+    /// 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>) -> Option<&'tcx [u8]> {
+        match self.ty.kind() {
+            ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
+                // `&str` can be interpreted as raw bytes
+                ty::Str => {}
+                // `&[u8]` can be interpreted as raw bytes
+                ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {}
+                // other `&_` can't be interpreted as raw bytes
+                _ => return None,
+            },
+            // `[u8; N]` can be interpreted as raw bytes
+            ty::Array(array_ty, _) if *array_ty == tcx.types.u8 => {}
+            // Otherwise, type cannot be interpreted as raw bytes
+            _ => return None,
+        }
+
+        Some(tcx.arena.alloc_from_iter(
+            self.valtree.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8()),
+        ))
+    }
 }
 
 impl<'tcx> rustc_type_ir::inherent::ValueConst<TyCtxt<'tcx>> for Value<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6c8591dae89..3431081b189 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1487,7 +1487,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             },
             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
             ty::ConstKind::Value(cv) => {
-                return self.pretty_print_const_valtree(cv.valtree, cv.ty, print_ty);
+                return self.pretty_print_const_valtree(cv, print_ty);
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
@@ -1787,48 +1787,47 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         Ok(())
     }
 
-    // FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
     fn pretty_print_const_valtree(
         &mut self,
-        valtree: ty::ValTree<'tcx>,
-        ty: Ty<'tcx>,
+        cv: ty::Value<'tcx>,
         print_ty: bool,
     ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
-            p!(write("ValTree({:?}: ", valtree), print(ty), ")");
+            p!(write("ValTree({:?}: ", cv.valtree), print(cv.ty), ")");
             return Ok(());
         }
 
         let u8_type = self.tcx().types.u8;
-        match (valtree, ty.kind()) {
+        match (cv.valtree, cv.ty.kind()) {
             (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
                 ty::Slice(t) if *t == u8_type => {
-                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                    let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
                         bug!(
                             "expected to convert valtree {:?} to raw bytes for type {:?}",
-                            valtree,
+                            cv.valtree,
                             t
                         )
                     });
                     return self.pretty_print_byte_str(bytes);
                 }
                 ty::Str => {
-                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
-                        bug!("expected to convert valtree to raw bytes for type {:?}", ty)
+                    let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
+                        bug!("expected to convert valtree to raw bytes for type {:?}", cv.ty)
                     });
                     p!(write("{:?}", String::from_utf8_lossy(bytes)));
                     return Ok(());
                 }
                 _ => {
+                    let cv = ty::Value { valtree: cv.valtree, ty: *inner_ty };
                     p!("&");
-                    p!(pretty_print_const_valtree(valtree, *inner_ty, print_ty));
+                    p!(pretty_print_const_valtree(cv, print_ty));
                     return Ok(());
                 }
             },
             (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
-                let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
                     bug!("expected to convert valtree to raw bytes for type {:?}", t)
                 });
                 p!("*");
@@ -1837,10 +1836,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
             (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
-                let contents =
-                    self.tcx().destructure_const(ty::Const::new_value(self.tcx(), valtree, ty));
+                let contents = self.tcx().destructure_const(ty::Const::new_value(
+                    self.tcx(),
+                    cv.valtree,
+                    cv.ty,
+                ));
                 let fields = contents.fields.iter().copied();
-                match *ty.kind() {
+                match *cv.ty.kind() {
                     ty::Array(..) => {
                         p!("[", comma_sep(fields), "]");
                     }
@@ -1857,7 +1859,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                                 write!(this, "unreachable()")?;
                                 Ok(())
                             },
-                            |this| this.print_type(ty),
+                            |this| this.print_type(cv.ty),
                             ": ",
                         )?;
                     }
@@ -1894,7 +1896,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 return self.pretty_print_const_scalar_int(leaf, *inner_ty, print_ty);
             }
             (ty::ValTree::Leaf(leaf), _) => {
-                return self.pretty_print_const_scalar_int(leaf, ty, print_ty);
+                return self.pretty_print_const_scalar_int(leaf, cv.ty, print_ty);
             }
             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
             // their fields instead of just dumping the memory.
@@ -1902,13 +1904,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
 
         // fallback
-        if valtree == ty::ValTree::zst() {
+        if cv.valtree == ty::ValTree::zst() {
             p!(write("<ZST>"));
         } else {
-            p!(write("{:?}", valtree));
+            p!(write("{:?}", cv.valtree));
         }
         if print_ty {
-            p!(": ", print(ty));
+            p!(": ", print(cv.ty));
         }
         Ok(())
     }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 9e9de4fb064..03b26b44538 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -170,7 +170,7 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> {
                     bug!("we checked that this is a valtree")
                 };
                 let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-                cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true)?;
+                cx.pretty_print_const_valtree(cv, /*print_ty*/ true)?;
                 f.write_str(&cx.into_buffer())
             });
         }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 7b040a8b2c4..0ac6f17b97b 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -649,7 +649,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                 // HACK(jaic1): hide the `str` type behind a reference
                 // for the following transformation from valtree to raw bytes
                 let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ct_ty);
-                let slice = valtree.try_to_raw_bytes(tcx, ref_ty).unwrap_or_else(|| {
+                let cv = ty::Value { ty: ref_ty, valtree };
+                let slice = cv.try_to_raw_bytes(tcx).unwrap_or_else(|| {
                     bug!("expected to get raw bytes from valtree {:?} for type {:}", valtree, ct_ty)
                 });
                 let s = std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");