Skip to content

Commit 6a66a27

Browse files
authored
Rollup merge of #136180 - lukas-code:typed-valtree, r=oli-obk
Introduce a wrapper for "typed valtrees" and properly check the type before extracting the value This PR adds a new wrapper type `ty::Value` to replace the tuple `(Ty, ty::ValTree)` and become the new canonical representation of type-level constant values. The value extraction methods `try_to_bits`/`try_to_bool`/`try_to_target_usize` are moved to this new type. For `try_to_bits` in particular, this avoids some redundant matches on `ty::ConstKind::Value`. Furthermore, these methods and will now properly check the type before extracting the value, which fixes some ICEs. The name `ty::Value` was chosen to be consistent with `ty::Expr`. Commit 1 should be non-functional and commit 2 adds the type check. --- fixes #131102 supercedes #136130 r? `@oli-obk` cc `@FedericoBruzzone` `@BoxyUwU`
2 parents 6c9c698 + ca3ff83 commit 6a66a27

File tree

50 files changed

+296
-225
lines changed

Some content is hidden

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

50 files changed

+296
-225
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

Lines changed: 1 addition & 6 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 6 additions & 10 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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/const_eval/valtrees.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
272272

273273
/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
274274
/// construction has finished.
275-
// FIXME Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
275+
// FIXME(valtrees): Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
276+
// FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
276277
#[instrument(skip(tcx), level = "debug", ret)]
277278
pub fn valtree_to_const_value<'tcx>(
278279
tcx: TyCtxt<'tcx>,

compiler/rustc_const_eval/src/lib.rs

Lines changed: 7 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 10 additions & 12 deletions
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.

0 commit comments

Comments
 (0)