Skip to content

Commit 092c29f

Browse files
committed
Stop using ty::Const in deref_const and destructure_const in preparation of value trees making such operations on ty::Const obsolete.
1 parent d80a0b4 commit 092c29f

File tree

12 files changed

+102
-55
lines changed

12 files changed

+102
-55
lines changed

compiler/rustc_codegen_ssa/src/mir/constant.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
5757
) -> (Bx::Value, Ty<'tcx>) {
5858
constant
5959
.map(|val| {
60-
let field_ty = ty.builtin_index().unwrap();
61-
let c = ty::Const::from_value(bx.tcx(), val, ty);
6260
let values: Vec<_> = bx
6361
.tcx()
64-
.destructure_const(ty::ParamEnv::reveal_all().and(&c))
62+
.destructure_const(ty::ParamEnv::reveal_all().and((val, ty)))
6563
.fields
6664
.iter()
67-
.map(|field| {
68-
if let Some(prim) = field.val.try_to_scalar() {
65+
.map(|(field, field_ty)| {
66+
if let Some(prim) = field.try_to_scalar() {
6967
let layout = bx.layout_of(field_ty);
7068
let scalar = match layout.abi {
7169
Abi::Scalar(ref x) => x,
@@ -78,7 +76,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
7876
})
7977
.collect();
8078
let llval = bx.const_struct(&values, false);
81-
(llval, c.ty)
79+
(llval, ty)
8280
})
8381
.unwrap_or_else(|_| {
8482
bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time");

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,6 +2506,27 @@ impl ConstantKind<'tcx> {
25062506
}
25072507
}
25082508

2509+
#[inline]
2510+
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2511+
pub fn eval_bits(
2512+
&self,
2513+
tcx: TyCtxt<'tcx>,
2514+
param_env: ty::ParamEnv<'tcx>,
2515+
ty: Ty<'tcx>,
2516+
) -> u128 {
2517+
match self {
2518+
Self::Ty(ct) => ct.eval_bits(tcx, param_env, ty),
2519+
Self::Val(val, t) => {
2520+
assert_eq!(*t, ty);
2521+
let size = tcx
2522+
.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty))
2523+
.expect("could not normalize type")
2524+
.size;
2525+
val.try_to_scalar_int().unwrap().assert_bits(size)
2526+
}
2527+
}
2528+
}
2529+
25092530
#[inline]
25102531
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
25112532
match self {

compiler/rustc_middle/src/mir/query.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use smallvec::SmallVec;
1515
use std::cell::Cell;
1616
use std::fmt::{self, Debug};
1717

18-
use super::{Field, SourceInfo};
18+
use super::{interpret::ConstValue, Field, SourceInfo};
1919

2020
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
2121
pub enum UnsafetyViolationKind {
@@ -386,7 +386,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
386386
#[derive(Copy, Clone, Debug, HashStable)]
387387
pub struct DestructuredConst<'tcx> {
388388
pub variant: Option<VariantIdx>,
389-
pub fields: &'tcx [&'tcx ty::Const<'tcx>],
389+
pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)],
390390
}
391391

392392
/// Coverage information summarized from a MIR if instrumented for source code coverage (see

compiler/rustc_middle/src/mir/type_foldable.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,13 @@ impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
367367
}
368368
}
369369
}
370+
371+
impl<'tcx> TypeFoldable<'tcx> for interpret::ConstValue<'tcx> {
372+
fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
373+
self
374+
}
375+
376+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
377+
ControlFlow::CONTINUE
378+
}
379+
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -808,16 +808,16 @@ rustc_queries! {
808808
/// Destructure a constant ADT or array into its variant index and its
809809
/// field values.
810810
query destructure_const(
811-
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
811+
key: ty::ParamEnvAnd<'tcx, (ConstValue<'tcx>, Ty<'tcx>)>
812812
) -> mir::DestructuredConst<'tcx> {
813813
desc { "destructure constant" }
814814
}
815815

816816
/// Dereference a constant reference or raw pointer and turn the result into a constant
817817
/// again.
818818
query deref_const(
819-
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
820-
) -> &'tcx ty::Const<'tcx> {
819+
key: ty::ParamEnvAnd<'tcx, (ConstValue<'tcx>, Ty<'tcx>)>
820+
) -> (ConstValue<'tcx>, Ty<'tcx>) {
821821
desc { "deref constant" }
822822
}
823823

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,10 +1190,8 @@ pub trait PrettyPrinter<'tcx>:
11901190
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
11911191
// correct `ty::ParamEnv` to allow printing *all* constant values.
11921192
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1193-
let contents = self.tcx().destructure_const(
1194-
ty::ParamEnv::reveal_all()
1195-
.and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
1196-
);
1193+
let contents =
1194+
self.tcx().destructure_const(ty::ParamEnv::reveal_all().and((ct, ty)));
11971195
let fields = contents.fields.iter().copied();
11981196

11991197
match *ty.kind() {

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
515515
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
516516
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
517517
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
518-
check_const_value_eq(relation, a_val, b_val, a, b)?
518+
check_const_value_eq(relation, a_val, b_val, a.ty, b.ty)?
519519
}
520520

521521
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
@@ -550,10 +550,8 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
550550
relation: &mut R,
551551
a_val: ConstValue<'tcx>,
552552
b_val: ConstValue<'tcx>,
553-
// FIXME(oli-obk): these arguments should go away with valtrees
554-
a: &'tcx ty::Const<'tcx>,
555-
b: &'tcx ty::Const<'tcx>,
556-
// FIXME(oli-obk): this should just be `bool` with valtrees
553+
a_ty: Ty<'tcx>,
554+
b_ty: Ty<'tcx>,
557555
) -> RelateResult<'tcx, bool> {
558556
let tcx = relation.tcx();
559557
Ok(match (a_val, b_val) {
@@ -575,13 +573,19 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
575573
}
576574

577575
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
578-
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
579-
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
576+
let a_destructured = tcx.destructure_const(relation.param_env().and((a_val, a_ty)));
577+
let b_destructured = tcx.destructure_const(relation.param_env().and((b_val, b_ty)));
580578

581579
// Both the variant and each field have to be equal.
582580
if a_destructured.variant == b_destructured.variant {
583-
for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
584-
relation.consts(a_field, b_field)?;
581+
for (&(a_val, a_ty), &(b_val, b_ty)) in iter::zip(a_destructured.fields, b_destructured.fields)
582+
{
583+
let is_match = check_const_value_eq(relation, a_val, b_val, a_ty, b_ty)?;
584+
if !is_match {
585+
let a = ty::Const::from_value(relation.tcx(), a_val, a_ty);
586+
let b = ty::Const::from_value(relation.tcx(), b_val, b_ty);
587+
return Err(TypeError::ConstMismatch(expected_found(relation, a, b)));
588+
}
585589
}
586590

587591
true

compiler/rustc_mir/src/const_eval/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::convert::TryFrom;
44

55
use rustc_hir::Mutability;
6-
use rustc_middle::ty::{self, TyCtxt};
6+
use rustc_middle::ty::{self, Ty, TyCtxt};
77
use rustc_middle::{
88
mir::{self, interpret::ConstAlloc},
99
ty::ScalarInt,
@@ -139,14 +139,15 @@ fn const_to_valtree_inner<'tcx>(
139139
pub(crate) fn destructure_const<'tcx>(
140140
tcx: TyCtxt<'tcx>,
141141
param_env: ty::ParamEnv<'tcx>,
142-
val: &'tcx ty::Const<'tcx>,
142+
val: ConstValue<'tcx>,
143+
ty: Ty<'tcx>,
143144
) -> mir::DestructuredConst<'tcx> {
144145
trace!("destructure_const: {:?}", val);
145146
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
146-
let op = ecx.const_to_op(val, None).unwrap();
147+
let op = ecx.const_val_to_op(val, ty, None).unwrap();
147148

148149
// We go to `usize` as we cannot allocate anything bigger anyway.
149-
let (field_count, variant, down) = match val.ty.kind() {
150+
let (field_count, variant, down) = match op.layout.ty.kind() {
150151
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
151152
ty::Adt(def, _) if def.variants.is_empty() => {
152153
return mir::DestructuredConst { variant: None, fields: &[] };
@@ -163,7 +164,7 @@ pub(crate) fn destructure_const<'tcx>(
163164
let fields_iter = (0..field_count).map(|i| {
164165
let field_op = ecx.operand_field(&down, i).unwrap();
165166
let val = op_to_const(&ecx, &field_op);
166-
ty::Const::from_value(tcx, val, field_op.layout.ty)
167+
(val, field_op.layout.ty)
167168
});
168169
let fields = tcx.arena.alloc_from_iter(fields_iter);
169170

@@ -173,11 +174,12 @@ pub(crate) fn destructure_const<'tcx>(
173174
pub(crate) fn deref_const<'tcx>(
174175
tcx: TyCtxt<'tcx>,
175176
param_env: ty::ParamEnv<'tcx>,
176-
val: &'tcx ty::Const<'tcx>,
177-
) -> &'tcx ty::Const<'tcx> {
177+
val: ConstValue<'tcx>,
178+
ty: Ty<'tcx>,
179+
) -> (ConstValue<'tcx>, Ty<'tcx>) {
178180
trace!("deref_const: {:?}", val);
179181
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
180-
let op = ecx.const_to_op(val, None).unwrap();
182+
let op = ecx.const_val_to_op(val, ty, None).unwrap();
181183
let mplace = ecx.deref_operand(&op).unwrap();
182184
if let Scalar::Ptr(ptr) = mplace.ptr {
183185
assert_eq!(
@@ -203,5 +205,5 @@ pub(crate) fn deref_const<'tcx>(
203205
},
204206
};
205207

206-
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
208+
(op_to_const(&ecx, &mplace.into()), ty)
207209
}

compiler/rustc_mir/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ pub fn provide(providers: &mut Providers) {
6262
providers.mir_callgraph_reachable = transform::inline::cycle::mir_callgraph_reachable;
6363
providers.mir_inliner_callees = transform::inline::cycle::mir_inliner_callees;
6464
providers.destructure_const = |tcx, param_env_and_value| {
65-
let (param_env, value) = param_env_and_value.into_parts();
66-
const_eval::destructure_const(tcx, param_env, value)
65+
let (param_env, (value, ty)) = param_env_and_value.into_parts();
66+
const_eval::destructure_const(tcx, param_env, value, ty)
6767
};
6868
providers.const_to_valtree = |tcx, param_env_and_value| {
6969
let (param_env, raw) = param_env_and_value.into_parts();
7070
const_eval::const_to_valtree(tcx, param_env, raw)
7171
};
7272
providers.deref_const = |tcx, param_env_and_value| {
73-
let (param_env, value) = param_env_and_value.into_parts();
74-
const_eval::deref_const(tcx, param_env, value)
73+
let (param_env, (value, ty)) = param_env_and_value.into_parts();
74+
const_eval::deref_const(tcx, param_env, value, ty)
7575
};
7676
}

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rustc_hir as hir;
22
use rustc_index::vec::Idx;
33
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
44
use rustc_middle::mir::Field;
5+
use rustc_middle::mir::interpret::ConstValue;
56
use rustc_middle::ty::print::with_no_trimmed_paths;
67
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
78
use rustc_session::lint;
@@ -248,11 +249,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
248249

249250
fn field_pats(
250251
&self,
251-
vals: impl Iterator<Item = &'tcx ty::Const<'tcx>>,
252+
vals: impl Iterator<Item = (ConstValue<'tcx>, Ty<'tcx>)>,
252253
) -> Result<Vec<FieldPat<'tcx>>, FallbackToConstRef> {
254+
let tcx = self.tcx();
253255
vals.enumerate()
254-
.map(|(idx, val)| {
256+
.map(|(idx, (val, ty))| {
255257
let field = Field::new(idx);
258+
let val = ty::Const::from_value(tcx, val, ty);
256259
Ok(FieldPat { field, pattern: self.recur(val, false)? })
257260
})
258261
.collect()
@@ -356,7 +359,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
356359
PatKind::Wild
357360
}
358361
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
359-
let destructured = tcx.destructure_const(param_env.and(cv));
362+
let destructured = tcx.destructure_const(param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
360363
PatKind::Variant {
361364
adt_def,
362365
substs,
@@ -367,15 +370,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
367370
}
368371
}
369372
ty::Tuple(_) | ty::Adt(_, _) => {
370-
let destructured = tcx.destructure_const(param_env.and(cv));
373+
let destructured = tcx.destructure_const(param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
371374
PatKind::Leaf { subpatterns: self.field_pats(destructured.fields.iter().copied())? }
372375
}
373376
ty::Array(..) => PatKind::Array {
374377
prefix: tcx
375-
.destructure_const(param_env.and(cv))
378+
.destructure_const(param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)))
376379
.fields
377380
.iter()
378-
.map(|val| self.recur(val, false))
381+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
379382
.collect::<Result<_, _>>()?,
380383
slice: None,
381384
suffix: Vec::new(),
@@ -403,15 +406,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
403406
// arrays.
404407
ty::Array(..) if !self.treat_byte_string_as_slice => {
405408
let old = self.behind_reference.replace(true);
406-
let array = tcx.deref_const(self.param_env.and(cv));
409+
let array = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
407410
let val = PatKind::Deref {
408411
subpattern: Pat {
409412
kind: Box::new(PatKind::Array {
410413
prefix: tcx
411414
.destructure_const(param_env.and(array))
412415
.fields
413416
.iter()
414-
.map(|val| self.recur(val, false))
417+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
415418
.collect::<Result<_, _>>()?,
416419
slice: None,
417420
suffix: vec![],
@@ -429,15 +432,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
429432
// pattern.
430433
ty::Slice(elem_ty) => {
431434
let old = self.behind_reference.replace(true);
432-
let array = tcx.deref_const(self.param_env.and(cv));
435+
let array = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
433436
let val = PatKind::Deref {
434437
subpattern: Pat {
435438
kind: Box::new(PatKind::Slice {
436439
prefix: tcx
437440
.destructure_const(param_env.and(array))
438441
.fields
439442
.iter()
440-
.map(|val| self.recur(val, false))
443+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
441444
.collect::<Result<_, _>>()?,
442445
slice: None,
443446
suffix: vec![],
@@ -492,7 +495,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
492495
// we fall back to a const pattern. If we do not do this, we may end up with
493496
// a !structural-match constant that is not of reference type, which makes it
494497
// very hard to invoke `PartialEq::eq` on it as a fallback.
495-
let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
498+
let (val, ty) = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
499+
let deref_cv = ty::Const::from_value(tcx, val, ty);
500+
let val = match self.recur(deref_cv, false) {
496501
Ok(subpattern) => PatKind::Deref { subpattern },
497502
Err(_) => PatKind::Constant { value: cv },
498503
};

compiler/rustc_query_impl/src/keys.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ impl<'tcx> Key for &'tcx ty::Const<'tcx> {
273273
}
274274
}
275275

276+
impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
277+
fn query_crate(&self) -> CrateNum {
278+
LOCAL_CRATE
279+
}
280+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
281+
DUMMY_SP
282+
}
283+
}
284+
276285
impl<'tcx> Key for Ty<'tcx> {
277286
fn query_crate(&self) -> CrateNum {
278287
LOCAL_CRATE

0 commit comments

Comments
 (0)