Skip to content

Commit 03d3088

Browse files
Lukas MarkeffskyFedericoBruzzone
Lukas Markeffsky
andcommitted
introduce ty::Value
Co-authored-by: FedericoBruzzone <[email protected]>
1 parent 66d6064 commit 03d3088

File tree

44 files changed

+214
-205
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+214
-205
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
129129
return;
130130
}
131131

132-
let idx = generic_args[2]
133-
.expect_const()
134-
.try_to_valtree()
135-
.expect("expected monomorphic const in codegen")
136-
.0
137-
.unwrap_branch();
132+
let idx = generic_args[2].expect_const().to_value().valtree.unwrap_branch();
138133

139134
assert_eq!(x.layout(), y.layout());
140135
let layout = x.layout();

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
13291329
}
13301330

13311331
if name == sym::simd_shuffle_generic {
1332-
let idx = fn_args[2].expect_const().try_to_valtree().unwrap().0.unwrap_branch();
1332+
let idx = fn_args[2].expect_const().to_value().valtree.unwrap_branch();
13331333
let n = idx.len() as u64;
13341334

13351335
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -673,25 +673,23 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
673673
ty::ConstKind::Param(param) => {
674674
write!(output, "{}", param.name)
675675
}
676-
ty::ConstKind::Value(ty, valtree) => {
677-
match ty.kind() {
676+
ty::ConstKind::Value(cv) => {
677+
match cv.ty.kind() {
678678
ty::Int(ity) => {
679-
// FIXME: directly extract the bits from a valtree instead of evaluating an
680-
// already evaluated `Const` in order to get the bits.
681-
let bits = ct
679+
let bits = cv
682680
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
683681
.expect("expected monomorphic const in codegen");
684682
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
685683
write!(output, "{val}")
686684
}
687685
ty::Uint(_) => {
688-
let val = ct
686+
let val = cv
689687
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
690688
.expect("expected monomorphic const in codegen");
691689
write!(output, "{val}")
692690
}
693691
ty::Bool => {
694-
let val = ct.try_to_bool().expect("expected monomorphic const in codegen");
692+
let val = cv.try_to_bool().expect("expected monomorphic const in codegen");
695693
write!(output, "{val}")
696694
}
697695
_ => {
@@ -703,9 +701,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
703701
// avoiding collisions and will make the emitted type names shorter.
704702
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
705703
let mut hasher = StableHasher::new();
706-
hcx.while_hashing_spans(false, |hcx| {
707-
(ty, valtree).hash_stable(hcx, &mut hasher)
708-
});
704+
hcx.while_hashing_spans(false, |hcx| cv.hash_stable(hcx, &mut hasher));
709705
hasher.finish::<Hash64>()
710706
});
711707

compiler/rustc_codegen_ssa/src/mir/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
4343
mir::Const::Ty(_, c) => match c.kind() {
4444
// A constant that came from a const generic but was then used as an argument to
4545
// old-style simd_shuffle (passing as argument instead of as a generic param).
46-
rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Ok(valtree)),
46+
rustc_type_ir::ConstKind::Value(cv) => return Ok(Ok(cv.valtree)),
4747
other => span_bug!(constant.span, "{other:#?}"),
4848
},
4949
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate

compiler/rustc_const_eval/src/check_consts/qualifs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ where
345345
Const::Ty(_, ct)
346346
if matches!(
347347
ct.kind(),
348-
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
348+
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
349349
) =>
350350
{
351351
None

compiler/rustc_const_eval/src/lib.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ pub fn provide(providers: &mut Providers) {
4646
};
4747
providers.hooks.try_destructure_mir_constant_for_user_output =
4848
const_eval::try_destructure_mir_constant_for_user_output;
49-
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
50-
const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), ty, valtree)
49+
providers.valtree_to_const_val = |tcx, cv| {
50+
const_eval::valtree_to_const_value(
51+
tcx,
52+
ty::TypingEnv::fully_monomorphized(),
53+
cv.ty,
54+
cv.valtree,
55+
)
5156
};
5257
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
5358
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)

compiler/rustc_infer/src/infer/freshen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
170170
}
171171

172172
ty::ConstKind::Param(_)
173-
| ty::ConstKind::Value(_, _)
173+
| ty::ConstKind::Value(_)
174174
| ty::ConstKind::Unevaluated(..)
175175
| ty::ConstKind::Expr(..)
176176
| ty::ConstKind::Error(_) => ct.super_fold_with(self),

compiler/rustc_infer/src/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ impl<'tcx> InferCtxt<'tcx> {
10551055
| ty::ConstKind::Bound(_, _)
10561056
| ty::ConstKind::Placeholder(_)
10571057
| ty::ConstKind::Unevaluated(_)
1058-
| ty::ConstKind::Value(_, _)
1058+
| ty::ConstKind::Value(_)
10591059
| ty::ConstKind::Error(_)
10601060
| ty::ConstKind::Expr(_) => ct,
10611061
}

compiler/rustc_middle/src/mir/consts.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl<'tcx> Const<'tcx> {
250250
// Dont use the outer ty as on invalid code we can wind up with them not being the same.
251251
// this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir
252252
// was originally `({N: usize} + 1_usize)` under `generic_const_exprs`.
253-
ty::ConstKind::Value(ty, _) => ty,
253+
ty::ConstKind::Value(cv) => cv.ty,
254254
_ => *ty,
255255
}
256256
}
@@ -264,7 +264,7 @@ impl<'tcx> Const<'tcx> {
264264
pub fn is_required_const(&self) -> bool {
265265
match self {
266266
Const::Ty(_, c) => match c.kind() {
267-
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
267+
ty::ConstKind::Value(_) => false, // already a value, cannot error
268268
_ => true,
269269
},
270270
Const::Val(..) => false, // already a value, cannot error
@@ -276,11 +276,11 @@ impl<'tcx> Const<'tcx> {
276276
pub fn try_to_scalar(self) -> Option<Scalar> {
277277
match self {
278278
Const::Ty(_, c) => match c.kind() {
279-
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
279+
ty::ConstKind::Value(cv) if cv.ty.is_primitive() => {
280280
// A valtree of a type where leaves directly represent the scalar const value.
281281
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
282282
// but the leaf value is the value they point to, not the reference itself!
283-
Some(valtree.unwrap_leaf().into())
283+
Some(cv.valtree.unwrap_leaf().into())
284284
}
285285
_ => None,
286286
},
@@ -295,9 +295,7 @@ impl<'tcx> Const<'tcx> {
295295
match self {
296296
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
297297
Const::Ty(_, c) => match c.kind() {
298-
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
299-
Some(valtree.unwrap_leaf())
300-
}
298+
ty::ConstKind::Value(cv) if cv.ty.is_primitive() => Some(cv.valtree.unwrap_leaf()),
301299
_ => None,
302300
},
303301
_ => None,
@@ -328,7 +326,7 @@ impl<'tcx> Const<'tcx> {
328326
}
329327

330328
match c.kind() {
331-
ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
329+
ConstKind::Value(cv) => Ok(tcx.valtree_to_const_val(cv)),
332330
ConstKind::Expr(_) => {
333331
bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
334332
}
@@ -353,13 +351,13 @@ impl<'tcx> Const<'tcx> {
353351
typing_env: ty::TypingEnv<'tcx>,
354352
) -> Option<Scalar> {
355353
if let Const::Ty(_, c) = self
356-
&& let ty::ConstKind::Value(ty, val) = c.kind()
357-
&& ty.is_primitive()
354+
&& let ty::ConstKind::Value(cv) = c.kind()
355+
&& cv.ty.is_primitive()
358356
{
359357
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
360358
// are valtree leaves, and *not* on references. (References should return the
361359
// pointer here, which valtrees don't represent.)
362-
Some(val.unwrap_leaf().into())
360+
Some(cv.valtree.unwrap_leaf().into())
363361
} else {
364362
self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar()
365363
}
@@ -473,7 +471,7 @@ impl<'tcx> Const<'tcx> {
473471
// A valtree may be a reference. Valtree references correspond to a
474472
// different allocation each time they are evaluated. Valtrees for primitive
475473
// types are fine though.
476-
ty::ConstKind::Value(ty, _) => ty.is_primitive(),
474+
ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
477475
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
478476
// This can happen if evaluation of a constant failed. The result does not matter
479477
// much since compilation is doomed.

compiler/rustc_middle/src/mir/pretty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
14411441
ty::ConstKind::Unevaluated(uv) => {
14421442
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
14431443
}
1444-
ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
1444+
ty::ConstKind::Value(cv) => {
1445+
format!("ty::Valtree({})", fmt_valtree(&cv.valtree))
1446+
}
14451447
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
14461448
ty::ConstKind::Error(_) => "Error".to_string(),
14471449
// These variants shouldn't exist in the MIR.

compiler/rustc_middle/src/query/keys.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
550550
}
551551
}
552552

553-
impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
553+
impl<'tcx> Key for ty::Value<'tcx> {
554554
type Cache<V> = DefaultCache<Self, V>;
555555

556556
fn default_span(&self, _: TyCtxt<'_>) -> Span {

compiler/rustc_middle/src/query/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1256,9 +1256,9 @@ rustc_queries! {
12561256
desc { "evaluating type-level constant" }
12571257
}
12581258

1259-
/// Converts a type level constant value into `ConstValue`
1260-
query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> mir::ConstValue<'tcx> {
1261-
desc { "converting type-level constant value to mir constant value"}
1259+
/// Converts a type-level constant value into a MIR constant value.
1260+
query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue<'tcx> {
1261+
desc { "converting type-level constant value to MIR constant value"}
12621262
}
12631263

12641264
/// Destructures array, ADT or tuple constants into the constants

compiler/rustc_middle/src/ty/consts.rs

+11-27
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ impl<'tcx> Const<'tcx> {
110110
}
111111

112112
#[inline]
113-
pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
114-
Const::new(tcx, ty::ConstKind::Value(ty, val))
113+
pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
114+
Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
115115
}
116116

117117
#[inline]
@@ -214,47 +214,31 @@ impl<'tcx> Const<'tcx> {
214214
Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
215215
}
216216

217-
/// Panics if self.kind != ty::ConstKind::Value
218-
pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) {
217+
/// Panics if `self.kind != ty::ConstKind::Value`.
218+
pub fn to_value(self) -> ty::Value<'tcx> {
219219
match self.kind() {
220-
ty::ConstKind::Value(ty, valtree) => (valtree, ty),
220+
ty::ConstKind::Value(cv) => cv,
221221
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
222222
}
223223
}
224224

225-
/// Attempts to convert to a `ValTree`
226-
pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> {
225+
/// Attempts to convert to a value.
226+
pub fn try_to_value(self) -> Option<ty::Value<'tcx>> {
227227
match self.kind() {
228-
ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)),
228+
ty::ConstKind::Value(cv) => Some(cv),
229229
_ => None,
230230
}
231231
}
232232

233233
#[inline]
234234
pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
235-
let (valtree, ty) = self.try_to_valtree()?;
236-
Some((valtree.try_to_scalar()?, ty))
237-
}
238-
239-
pub fn try_to_bool(self) -> Option<bool> {
240-
self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok()
235+
let cv = self.try_to_value()?;
236+
Some((cv.valtree.try_to_scalar()?, cv.ty))
241237
}
242238

243239
#[inline]
244240
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
245-
self.try_to_valtree()?.0.try_to_target_usize(tcx)
246-
}
247-
248-
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
249-
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
250-
/// contains const generic parameters or pointers).
251-
#[inline]
252-
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
253-
let (scalar, ty) = self.try_to_scalar()?;
254-
let scalar = scalar.try_to_scalar_int().ok()?;
255-
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
256-
let size = tcx.layout_of(input).ok()?.size;
257-
Some(scalar.to_bits(size))
241+
self.try_to_value()?.try_to_target_usize(tcx)
258242
}
259243

260244
pub fn is_ct_infer(self) -> bool {

compiler/rustc_middle/src/ty/consts/valtree.rs

+44-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
1+
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
22

33
use super::ScalarInt;
44
use crate::mir::interpret::Scalar;
55
use crate::ty::{self, Ty, TyCtxt};
66

7-
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)]
8-
#[derive(HashStable)]
97
/// This datastructure is used to represent the value of constants used in the type system.
108
///
119
/// We explicitly choose a different datastructure from the way values are processed within
@@ -18,6 +16,8 @@ use crate::ty::{self, Ty, TyCtxt};
1816
///
1917
/// `ValTree` does not have this problem with representation, as it only contains integers or
2018
/// lists of (nested) `ValTree`.
19+
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
20+
#[derive(HashStable, TyEncodable, TyDecodable)]
2121
pub enum ValTree<'tcx> {
2222
/// integers, `bool`, `char` are represented as scalars.
2323
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
@@ -79,10 +79,6 @@ impl<'tcx> ValTree<'tcx> {
7979
}
8080
}
8181

82-
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
83-
self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
84-
}
85-
8682
/// Get the values inside the ValTree as a slice of bytes. This only works for
8783
/// constants with types &str, &[u8], or [u8; _].
8884
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
@@ -107,3 +103,44 @@ impl<'tcx> ValTree<'tcx> {
107103
)
108104
}
109105
}
106+
107+
/// A type-level constant value.
108+
///
109+
/// Represents a typed, fully evaluated constant.
110+
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
111+
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
112+
pub struct Value<'tcx> {
113+
pub ty: Ty<'tcx>,
114+
pub valtree: ValTree<'tcx>,
115+
}
116+
117+
impl<'tcx> Value<'tcx> {
118+
/// Attempts to extract the raw bits from the constant.
119+
///
120+
/// Fails if the value can't be represented as bits (e.g. because it is an aggregate).
121+
#[inline]
122+
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
123+
let scalar = self.valtree.try_to_scalar_int()?;
124+
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty);
125+
let size = tcx.layout_of(input).ok()?.size;
126+
Some(scalar.to_bits(size))
127+
}
128+
129+
pub fn try_to_bool(self) -> Option<bool> {
130+
self.valtree.try_to_scalar_int()?.try_to_bool().ok()
131+
}
132+
133+
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
134+
self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
135+
}
136+
}
137+
138+
impl<'tcx> rustc_type_ir::inherent::ValueConst<TyCtxt<'tcx>> for Value<'tcx> {
139+
fn ty(self) -> Ty<'tcx> {
140+
self.ty
141+
}
142+
143+
fn valtree(self) -> ValTree<'tcx> {
144+
self.valtree
145+
}
146+
}

0 commit comments

Comments
 (0)