Skip to content

Commit 77215d3

Browse files
authored
Unrolled build for #136180
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 a730edc + ca3ff83 commit 77215d3

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

+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/const_eval/valtrees.rs

+2-1
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

+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

+15-32
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan;
55
use rustc_macros::HashStable;
66
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
77

8-
use crate::mir::interpret::Scalar;
98
use crate::ty::{self, Ty, TyCtxt};
109

1110
mod int;
@@ -110,8 +109,8 @@ impl<'tcx> Const<'tcx> {
110109
}
111110

112111
#[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))
112+
pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
113+
Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
115114
}
116115

117116
#[inline]
@@ -214,47 +213,31 @@ impl<'tcx> Const<'tcx> {
214213
Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
215214
}
216215

217-
/// Panics if self.kind != ty::ConstKind::Value
218-
pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) {
216+
/// Panics if `self.kind != ty::ConstKind::Value`.
217+
pub fn to_value(self) -> ty::Value<'tcx> {
219218
match self.kind() {
220-
ty::ConstKind::Value(ty, valtree) => (valtree, ty),
219+
ty::ConstKind::Value(cv) => cv,
221220
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
222221
}
223222
}
224223

225-
/// Attempts to convert to a `ValTree`
226-
pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> {
224+
/// Attempts to convert to a value.
225+
///
226+
/// Note that this does not evaluate the constant.
227+
pub fn try_to_value(self) -> Option<ty::Value<'tcx>> {
227228
match self.kind() {
228-
ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)),
229+
ty::ConstKind::Value(cv) => Some(cv),
229230
_ => None,
230231
}
231232
}
232233

233-
#[inline]
234-
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()
241-
}
242-
234+
/// Convenience method to extract the value of a usize constant,
235+
/// useful to get the length of an array type.
236+
///
237+
/// Note that this does not evaluate the constant.
243238
#[inline]
244239
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))
240+
self.try_to_value()?.try_to_target_usize(tcx)
258241
}
259242

260243
pub fn is_ct_infer(self) -> bool {

0 commit comments

Comments
 (0)