Skip to content

Commit 562cbc9

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 b2a2286 commit 562cbc9

File tree

12 files changed

+109
-55
lines changed

12 files changed

+109
-55
lines changed

compiler/rustc_codegen_ssa/src/mir/constant.rs

+4-6
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

+21
Original file line numberDiff line numberDiff line change
@@ -2543,6 +2543,27 @@ impl ConstantKind<'tcx> {
25432543
}
25442544
}
25452545

2546+
#[inline]
2547+
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2548+
pub fn eval_bits(
2549+
&self,
2550+
tcx: TyCtxt<'tcx>,
2551+
param_env: ty::ParamEnv<'tcx>,
2552+
ty: Ty<'tcx>,
2553+
) -> u128 {
2554+
match self {
2555+
Self::Ty(ct) => ct.eval_bits(tcx, param_env, ty),
2556+
Self::Val(val, t) => {
2557+
assert_eq!(*t, ty);
2558+
let size = tcx
2559+
.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty))
2560+
.expect("could not normalize type")
2561+
.size;
2562+
val.try_to_scalar_int().unwrap().assert_bits(size)
2563+
}
2564+
}
2565+
}
2566+
25462567
#[inline]
25472568
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
25482569
match self {

compiler/rustc_middle/src/mir/query.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use smallvec::SmallVec;
1616
use std::cell::Cell;
1717
use std::fmt::{self, Debug};
1818

19-
use super::{Field, SourceInfo};
19+
use super::{interpret::ConstValue, Field, SourceInfo};
2020

2121
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
2222
pub enum UnsafetyViolationKind {
@@ -379,7 +379,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
379379
#[derive(Copy, Clone, Debug, HashStable)]
380380
pub struct DestructuredConst<'tcx> {
381381
pub variant: Option<VariantIdx>,
382-
pub fields: &'tcx [&'tcx ty::Const<'tcx>],
382+
pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)],
383383
}
384384

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

compiler/rustc_middle/src/mir/type_foldable.rs

+10
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

+3-3
Original file line numberDiff line numberDiff line change
@@ -828,16 +828,16 @@ rustc_queries! {
828828
/// Destructure a constant ADT or array into its variant index and its
829829
/// field values.
830830
query destructure_const(
831-
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
831+
key: ty::ParamEnvAnd<'tcx, (ConstValue<'tcx>, Ty<'tcx>)>
832832
) -> mir::DestructuredConst<'tcx> {
833833
desc { "destructure constant" }
834834
}
835835

836836
/// Dereference a constant reference or raw pointer and turn the result into a constant
837837
/// again.
838838
query deref_const(
839-
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
840-
) -> &'tcx ty::Const<'tcx> {
839+
key: ty::ParamEnvAnd<'tcx, (ConstValue<'tcx>, Ty<'tcx>)>
840+
) -> (ConstValue<'tcx>, Ty<'tcx>) {
841841
desc { "deref constant" }
842842
}
843843

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -1200,10 +1200,8 @@ pub trait PrettyPrinter<'tcx>:
12001200
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
12011201
// correct `ty::ParamEnv` to allow printing *all* constant values.
12021202
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1203-
let contents = self.tcx().destructure_const(
1204-
ty::ParamEnv::reveal_all()
1205-
.and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
1206-
);
1203+
let contents =
1204+
self.tcx().destructure_const(ty::ParamEnv::reveal_all().and((ct, ty)));
12071205
let fields = contents.fields.iter().copied();
12081206

12091207
match *ty.kind() {

compiler/rustc_middle/src/ty/relate.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
546546
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
547547
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
548548
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
549-
check_const_value_eq(relation, a_val, b_val, a, b)?
549+
check_const_value_eq(relation, a_val, b_val, a.ty, b.ty)?
550550
}
551551

552552
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
@@ -585,10 +585,8 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
585585
relation: &mut R,
586586
a_val: ConstValue<'tcx>,
587587
b_val: ConstValue<'tcx>,
588-
// FIXME(oli-obk): these arguments should go away with valtrees
589-
a: &'tcx ty::Const<'tcx>,
590-
b: &'tcx ty::Const<'tcx>,
591-
// FIXME(oli-obk): this should just be `bool` with valtrees
588+
a_ty: Ty<'tcx>,
589+
b_ty: Ty<'tcx>,
592590
) -> RelateResult<'tcx, bool> {
593591
let tcx = relation.tcx();
594592
Ok(match (a_val, b_val) {
@@ -610,13 +608,20 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
610608
}
611609

612610
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
613-
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
614-
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
611+
let a_destructured = tcx.destructure_const(relation.param_env().and((a_val, a_ty)));
612+
let b_destructured = tcx.destructure_const(relation.param_env().and((b_val, b_ty)));
615613

616614
// Both the variant and each field have to be equal.
617615
if a_destructured.variant == b_destructured.variant {
618-
for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
619-
relation.consts(a_field, b_field)?;
616+
for (&(a_val, a_ty), &(b_val, b_ty)) in
617+
iter::zip(a_destructured.fields, b_destructured.fields)
618+
{
619+
let is_match = check_const_value_eq(relation, a_val, b_val, a_ty, b_ty)?;
620+
if !is_match {
621+
let a = ty::Const::from_value(relation.tcx(), a_val, a_ty);
622+
let b = ty::Const::from_value(relation.tcx(), b_val, b_ty);
623+
return Err(TypeError::ConstMismatch(expected_found(relation, a, b)));
624+
}
620625
}
621626

622627
true

compiler/rustc_mir/src/const_eval/mod.rs

+11-9
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

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ pub fn provide(providers: &mut Providers) {
6161
providers.mir_callgraph_reachable = transform::inline::cycle::mir_callgraph_reachable;
6262
providers.mir_inliner_callees = transform::inline::cycle::mir_inliner_callees;
6363
providers.destructure_const = |tcx, param_env_and_value| {
64-
let (param_env, value) = param_env_and_value.into_parts();
65-
const_eval::destructure_const(tcx, param_env, value)
64+
let (param_env, (value, ty)) = param_env_and_value.into_parts();
65+
const_eval::destructure_const(tcx, param_env, value, ty)
6666
};
6767
providers.const_to_valtree = |tcx, param_env_and_value| {
6868
let (param_env, raw) = param_env_and_value.into_parts();
6969
const_eval::const_to_valtree(tcx, param_env, raw)
7070
};
7171
providers.deref_const = |tcx, param_env_and_value| {
72-
let (param_env, value) = param_env_and_value.into_parts();
73-
const_eval::deref_const(tcx, param_env, value)
72+
let (param_env, (value, ty)) = param_env_and_value.into_parts();
73+
const_eval::deref_const(tcx, param_env, value, ty)
7474
};
7575
}

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

+22-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_hir as hir;
22
use rustc_index::vec::Idx;
33
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
4+
use rustc_middle::mir::interpret::ConstValue;
45
use rustc_middle::mir::Field;
56
use rustc_middle::thir::{FieldPat, Pat, PatKind};
67
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -249,11 +250,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
249250

250251
fn field_pats(
251252
&self,
252-
vals: impl Iterator<Item = &'tcx ty::Const<'tcx>>,
253+
vals: impl Iterator<Item = (ConstValue<'tcx>, Ty<'tcx>)>,
253254
) -> Result<Vec<FieldPat<'tcx>>, FallbackToConstRef> {
255+
let tcx = self.tcx();
254256
vals.enumerate()
255-
.map(|(idx, val)| {
257+
.map(|(idx, (val, ty))| {
256258
let field = Field::new(idx);
259+
let val = ty::Const::from_value(tcx, val, ty);
257260
Ok(FieldPat { field, pattern: self.recur(val, false)? })
258261
})
259262
.collect()
@@ -357,7 +360,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
357360
PatKind::Wild
358361
}
359362
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
360-
let destructured = tcx.destructure_const(param_env.and(cv));
363+
let destructured = tcx.destructure_const(
364+
param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)),
365+
);
361366
PatKind::Variant {
362367
adt_def,
363368
substs,
@@ -368,15 +373,19 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
368373
}
369374
}
370375
ty::Tuple(_) | ty::Adt(_, _) => {
371-
let destructured = tcx.destructure_const(param_env.and(cv));
376+
let destructured = tcx.destructure_const(
377+
param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)),
378+
);
372379
PatKind::Leaf { subpatterns: self.field_pats(destructured.fields.iter().copied())? }
373380
}
374381
ty::Array(..) => PatKind::Array {
375382
prefix: tcx
376-
.destructure_const(param_env.and(cv))
383+
.destructure_const(
384+
param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)),
385+
)
377386
.fields
378387
.iter()
379-
.map(|val| self.recur(val, false))
388+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
380389
.collect::<Result<_, _>>()?,
381390
slice: None,
382391
suffix: Vec::new(),
@@ -404,15 +413,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
404413
// arrays.
405414
ty::Array(..) if !self.treat_byte_string_as_slice => {
406415
let old = self.behind_reference.replace(true);
407-
let array = tcx.deref_const(self.param_env.and(cv));
416+
let array = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
408417
let val = PatKind::Deref {
409418
subpattern: Pat {
410419
kind: Box::new(PatKind::Array {
411420
prefix: tcx
412421
.destructure_const(param_env.and(array))
413422
.fields
414423
.iter()
415-
.map(|val| self.recur(val, false))
424+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
416425
.collect::<Result<_, _>>()?,
417426
slice: None,
418427
suffix: vec![],
@@ -430,15 +439,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
430439
// pattern.
431440
ty::Slice(elem_ty) => {
432441
let old = self.behind_reference.replace(true);
433-
let array = tcx.deref_const(self.param_env.and(cv));
442+
let array = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
434443
let val = PatKind::Deref {
435444
subpattern: Pat {
436445
kind: Box::new(PatKind::Slice {
437446
prefix: tcx
438447
.destructure_const(param_env.and(array))
439448
.fields
440449
.iter()
441-
.map(|val| self.recur(val, false))
450+
.map(|&(val, ty)| self.recur(ty::Const::from_value(tcx, val, ty), false))
442451
.collect::<Result<_, _>>()?,
443452
slice: None,
444453
suffix: vec![],
@@ -493,7 +502,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
493502
// we fall back to a const pattern. If we do not do this, we may end up with
494503
// a !structural-match constant that is not of reference type, which makes it
495504
// very hard to invoke `PartialEq::eq` on it as a fallback.
496-
let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
505+
let (val, ty) = tcx.deref_const(self.param_env.and((cv.val.eval(tcx, param_env).try_to_value().unwrap(), cv.ty)));
506+
let deref_cv = ty::Const::from_value(tcx, val, ty);
507+
let val = match self.recur(deref_cv, false) {
497508
Ok(subpattern) => PatKind::Deref { subpattern },
498509
Err(_) => PatKind::Constant { value: cv },
499510
};

compiler/rustc_query_impl/src/keys.rs

+9
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,15 @@ impl<'tcx> Key for &'tcx ty::Const<'tcx> {
311311
}
312312
}
313313

314+
impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
315+
fn query_crate_is_local(&self) -> bool {
316+
true
317+
}
318+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
319+
DUMMY_SP
320+
}
321+
}
322+
314323
impl<'tcx> Key for Ty<'tcx> {
315324
#[inline(always)]
316325
fn query_crate_is_local(&self) -> bool {

0 commit comments

Comments
 (0)