Skip to content

Commit 34f1707

Browse files
committed
Add Ty to ConstKind::Value
1 parent 0fea726 commit 34f1707

File tree

30 files changed

+183
-189
lines changed

30 files changed

+183
-189
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
12011201
.expect_const()
12021202
.eval(tcx, ty::ParamEnv::reveal_all(), span)
12031203
.unwrap()
1204+
.1
12041205
.unwrap_branch();
12051206
let n = idx.len() as u64;
12061207

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+38-34
Original file line numberDiff line numberDiff line change
@@ -693,42 +693,46 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
693693
ty::ConstKind::Param(param) => {
694694
write!(output, "{}", param.name)
695695
}
696-
// THISPR
697-
_ => match { todo!() as Ty<'tcx> }.kind() {
698-
ty::Int(ity) => {
699-
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
700-
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
701-
write!(output, "{val}")
702-
}
703-
ty::Uint(_) => {
704-
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
705-
write!(output, "{val}")
706-
}
707-
ty::Bool => {
708-
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
709-
write!(output, "{val}")
710-
}
711-
_ => {
712-
// If we cannot evaluate the constant to a known type, we fall back
713-
// to emitting a stable hash value of the constant. This isn't very pretty
714-
// but we get a deterministic, virtually unique value for the constant.
715-
//
716-
// Let's only emit 64 bits of the hash value. That should be plenty for
717-
// avoiding collisions and will make the emitted type names shorter.
718-
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
719-
let mut hasher = StableHasher::new();
720-
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
721-
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
722-
hasher.finish::<Hash64>()
723-
});
724-
725-
if cpp_like_debuginfo(tcx) {
726-
write!(output, "CONST${hash_short:x}")
727-
} else {
728-
write!(output, "{{CONST#{hash_short:x}}}")
696+
ty::ConstKind::Value(ty, _) => {
697+
match ty.kind() {
698+
ty::Int(ity) => {
699+
// FIXME: directly extract the bits from a valtree instead of evaluating an
700+
// alreay evaluated `Const` in order to get the bits.
701+
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
702+
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
703+
write!(output, "{val}")
704+
}
705+
ty::Uint(_) => {
706+
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
707+
write!(output, "{val}")
708+
}
709+
ty::Bool => {
710+
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
711+
write!(output, "{val}")
712+
}
713+
_ => {
714+
// If we cannot evaluate the constant to a known type, we fall back
715+
// to emitting a stable hash value of the constant. This isn't very pretty
716+
// but we get a deterministic, virtually unique value for the constant.
717+
//
718+
// Let's only emit 64 bits of the hash value. That should be plenty for
719+
// avoiding collisions and will make the emitted type names shorter.
720+
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
721+
let mut hasher = StableHasher::new();
722+
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
723+
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
724+
hasher.finish::<Hash64>()
725+
});
726+
727+
if cpp_like_debuginfo(tcx) {
728+
write!(output, "CONST${hash_short:x}")
729+
} else {
730+
write!(output, "{{CONST#{hash_short:x}}}")
731+
}
729732
}
730733
}
731-
},
734+
}
735+
_ => bug!("Invalid `Const` during codegen: {:?}", ct),
732736
}
733737
.unwrap();
734738
}

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 old-style
4545
// simd_shuffle (passing as argument instead of as a generic param).
46-
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
46+
rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(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
@@ -360,7 +360,7 @@ where
360360
Const::Ty(ct)
361361
if matches!(
362362
ct.kind(),
363-
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
363+
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
364364
) =>
365365
{
366366
None

compiler/rustc_hir_typeck/src/pat.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2409,7 +2409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24092409
min_len: u64,
24102410
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
24112411
let len = match len.eval(self.tcx, self.param_env, span) {
2412-
Ok(val) => val
2412+
// FIXME(BoxyUwU): Assert the `Ty` is a `usize`?
2413+
Ok((_, val)) => val
24132414
.try_to_scalar()
24142415
.and_then(|scalar| scalar.try_to_int().ok())
24152416
.and_then(|int| int.try_to_target_usize(self.tcx).ok()),

compiler/rustc_infer/src/infer/freshen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
176176
}
177177

178178
ty::ConstKind::Param(_)
179-
| ty::ConstKind::Value(_)
179+
| ty::ConstKind::Value(_, _)
180180
| ty::ConstKind::Unevaluated(..)
181181
| ty::ConstKind::Expr(..)
182182
| ty::ConstKind::Error(_) => ct.super_fold_with(self),

compiler/rustc_infer/src/infer/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ impl<'tcx> InferCtxt<'tcx> {
12991299
| ty::ConstKind::Bound(_, _)
13001300
| ty::ConstKind::Placeholder(_)
13011301
| ty::ConstKind::Unevaluated(_)
1302-
| ty::ConstKind::Value(_)
1302+
| ty::ConstKind::Value(_, _)
13031303
| ty::ConstKind::Error(_)
13041304
| ty::ConstKind::Expr(_) => ct,
13051305
}
@@ -1514,8 +1514,11 @@ impl<'tcx> InferCtxt<'tcx> {
15141514
span: Span,
15151515
) -> Result<ty::Const<'tcx>, ErrorHandled> {
15161516
match self.const_eval_resolve(param_env, unevaluated, span) {
1517-
// THISPR
1518-
Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, todo!())),
1517+
Ok(Some(val)) => Ok(ty::Const::new_value(
1518+
self.tcx,
1519+
val,
1520+
self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
1521+
)),
15191522
Ok(None) => {
15201523
let tcx = self.tcx;
15211524
let def_id = unevaluated.def;

compiler/rustc_middle/src/mir/consts.rs

+21-27
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl<'tcx> Const<'tcx> {
249249
pub fn is_required_const(&self) -> bool {
250250
match self {
251251
Const::Ty(c) => match c.kind() {
252-
ty::ConstKind::Value(_) => false, // already a value, cannot error
252+
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
253253
_ => true,
254254
},
255255
Const::Val(..) => false, // already a value, cannot error
@@ -261,9 +261,7 @@ impl<'tcx> Const<'tcx> {
261261
pub fn try_to_scalar(self) -> Option<Scalar> {
262262
match self {
263263
Const::Ty(c) => match c.kind() {
264-
// THISPR
265-
// if c.ty().is_primitive()
266-
ty::ConstKind::Value(valtree) if todo!() => {
264+
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
267265
// A valtree of a type where leaves directly represent the scalar const value.
268266
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
269267
// but the leaf value is the value they point to, not the reference itself!
@@ -282,9 +280,9 @@ impl<'tcx> Const<'tcx> {
282280
match self {
283281
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
284282
Const::Ty(c) => match c.kind() {
285-
// THISPR
286-
// if c.ty().is_primitive()
287-
ty::ConstKind::Value(valtree) if todo!() => Some(valtree.unwrap_leaf()),
283+
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
284+
Some(valtree.unwrap_leaf())
285+
}
288286
_ => None,
289287
},
290288
_ => None,
@@ -312,8 +310,8 @@ impl<'tcx> Const<'tcx> {
312310
Const::Ty(c) => {
313311
// We want to consistently have a "clean" value for type system constants (i.e., no
314312
// data hidden in the padding), so we always go through a valtree here.
315-
let val = c.eval(tcx, param_env, span)?;
316-
Ok(tcx.valtree_to_const_val((self.ty(), val)))
313+
let (ty, val) = c.eval(tcx, param_env, span)?;
314+
Ok(tcx.valtree_to_const_val((ty, val)))
317315
}
318316
Const::Unevaluated(uneval, _) => {
319317
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
@@ -341,17 +339,16 @@ impl<'tcx> Const<'tcx> {
341339
tcx: TyCtxt<'tcx>,
342340
param_env: ty::ParamEnv<'tcx>,
343341
) -> Option<Scalar> {
344-
match self {
345-
// THISPR
346-
// c.ty().is_primitive()
347-
Const::Ty(c) if todo!() => {
348-
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
349-
// are valtree leaves, and *not* on references. (References should return the
350-
// pointer here, which valtrees don't represent.)
351-
let val = c.eval(tcx, param_env, DUMMY_SP).ok()?;
352-
Some(val.unwrap_leaf().into())
353-
}
354-
_ => self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar(),
342+
if let Const::Ty(c) = self
343+
&& let ty::ConstKind::Value(ty, val) = c.kind()
344+
&& ty.is_primitive()
345+
{
346+
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
347+
// are valtree leaves, and *not* on references. (References should return the
348+
// pointer here, which valtrees don't represent.)
349+
Some(val.unwrap_leaf().into())
350+
} else {
351+
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
355352
}
356353
}
357354

@@ -446,11 +443,10 @@ impl<'tcx> Const<'tcx> {
446443

447444
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
448445
match c.kind() {
449-
ty::ConstKind::Value(valtree) => {
446+
ty::ConstKind::Value(ty, valtree) => {
450447
// Make sure that if `c` is normalized, then the return value is normalized.
451-
// THISPR
452-
let const_val = tcx.valtree_to_const_val((todo!(), valtree));
453-
Self::Val(const_val, todo!())
448+
let const_val = tcx.valtree_to_const_val((ty, valtree));
449+
Self::Val(const_val, ty)
454450
}
455451
_ => Self::Ty(c),
456452
}
@@ -469,9 +465,7 @@ impl<'tcx> Const<'tcx> {
469465
// A valtree may be a reference. Valtree references correspond to a
470466
// different allocation each time they are evaluated. Valtrees for primitive
471467
// types are fine though.
472-
// THISPR
473-
// c.ty().is_primitive()
474-
ty::ConstKind::Value(_) => todo!(),
468+
ty::ConstKind::Value(ty, _) => ty.is_primitive(),
475469
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
476470
// This can happen if evaluation of a constant failed. The result does not matter
477471
// much since compilation is doomed.

compiler/rustc_middle/src/mir/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
13181318
ty::ConstKind::Unevaluated(uv) => {
13191319
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
13201320
}
1321-
ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)),
1321+
ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
13221322
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
13231323
ty::ConstKind::Error(_) => "Error".to_string(),
13241324
// These variants shouldn't exist in the MIR.

compiler/rustc_middle/src/ty/consts.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
2424
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
2525

2626
#[cfg(target_pointer_width = "64")]
27-
rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
27+
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
2828

2929
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
3030
#[rustc_pass_by_value]
@@ -168,10 +168,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
168168
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
169169
Const::new_unevaluated(interner, uv)
170170
}
171-
172-
fn ty(self) -> Ty<'tcx> {
173-
self.ty()
174-
}
175171
}
176172

177173
impl<'tcx> Const<'tcx> {
@@ -311,7 +307,7 @@ impl<'tcx> Const<'tcx> {
311307
tcx: TyCtxt<'tcx>,
312308
param_env: ParamEnv<'tcx>,
313309
span: Span,
314-
) -> Result<ValTree<'tcx>, ErrorHandled> {
310+
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
315311
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
316312
match self.kind() {
317313
ConstKind::Unevaluated(unevaluated) => {
@@ -329,9 +325,9 @@ impl<'tcx> Const<'tcx> {
329325
);
330326
return Err(e.into());
331327
};
332-
Ok(c)
328+
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
333329
}
334-
ConstKind::Value(val) => Ok(val),
330+
ConstKind::Value(ty, val) => Ok((ty, val)),
335331
ConstKind::Error(g) => Err(g.into()),
336332
ConstKind::Param(_)
337333
| ConstKind::Infer(_)
@@ -345,7 +341,7 @@ impl<'tcx> Const<'tcx> {
345341
#[inline]
346342
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
347343
match self.eval(tcx, param_env, DUMMY_SP) {
348-
Ok(val) => Self::new_value(tcx, val, self.ty_for_ctfe(tcx).unwrap()),
344+
Ok((ty, val)) => Self::new_value(tcx, val, ty),
349345
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
350346
Err(ErrorHandled::TooGeneric(_span)) => self,
351347
}
@@ -356,8 +352,10 @@ impl<'tcx> Const<'tcx> {
356352
self,
357353
tcx: TyCtxt<'tcx>,
358354
param_env: ty::ParamEnv<'tcx>,
359-
) -> Option<Scalar> {
360-
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
355+
) -> Option<(Ty<'tcx>, Scalar)> {
356+
let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
357+
let val = val.try_to_scalar()?;
358+
Some((ty, val))
361359
}
362360

363361
#[inline]
@@ -368,24 +366,21 @@ impl<'tcx> Const<'tcx> {
368366
self,
369367
tcx: TyCtxt<'tcx>,
370368
param_env: ParamEnv<'tcx>,
371-
) -> Option<ScalarInt> {
372-
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
369+
) -> Option<(Ty<'tcx>, ScalarInt)> {
370+
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
371+
let val = scalar.try_to_int().ok()?;
372+
Some((ty, val))
373373
}
374374

375375
#[inline]
376376
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
377377
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
378378
/// contains const generic parameters or pointers).
379379
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
380-
let int = self.try_eval_scalar_int(tcx, param_env)?;
381-
let size = tcx
382-
.layout_of(
383-
param_env.with_reveal_all_normalized(tcx).and(self.ty_for_ctfe(tcx).unwrap()),
384-
)
385-
.ok()?
386-
.size;
380+
let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
381+
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
387382
// if `ty` does not depend on generic parameters, use an empty param_env
388-
int.try_to_bits(size).ok()
383+
scalar.try_to_bits(size).ok()
389384
}
390385

391386
#[inline]
@@ -401,12 +396,14 @@ impl<'tcx> Const<'tcx> {
401396
tcx: TyCtxt<'tcx>,
402397
param_env: ParamEnv<'tcx>,
403398
) -> Option<u64> {
404-
self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
399+
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
400+
scalar.try_to_target_usize(tcx).ok()
405401
}
406402

407403
#[inline]
408404
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
409-
self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
405+
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
406+
scalar.try_into().ok()
410407
}
411408

412409
#[inline]
@@ -419,15 +416,15 @@ impl<'tcx> Const<'tcx> {
419416
/// Panics if self.kind != ty::ConstKind::Value
420417
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
421418
match self.kind() {
422-
ty::ConstKind::Value(valtree) => valtree,
419+
ty::ConstKind::Value(_, valtree) => valtree,
423420
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
424421
}
425422
}
426423

427424
/// Attempts to convert to a `ValTree`
428425
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
429426
match self.kind() {
430-
ty::ConstKind::Value(valtree) => Some(valtree),
427+
ty::ConstKind::Value(_, valtree) => Some(valtree),
431428
_ => None,
432429
}
433430
}

0 commit comments

Comments
 (0)