Skip to content

Commit c423a86

Browse files
committed
Change const eval to return ConstValue, instead of Const as the type inside it shouldn't be used.
1 parent e168dcd commit c423a86

File tree

20 files changed

+145
-80
lines changed

20 files changed

+145
-80
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
22

33
use crate::hir::map::definitions::DefPathData;
44
use crate::mir;
5+
use crate::mir::interpret::ConstValue;
56
use crate::ty::layout::{Align, LayoutError, Size};
67
use crate::ty::query::TyCtxtAt;
78
use crate::ty::{self, layout, Ty};
@@ -40,7 +41,7 @@ CloneTypeFoldableImpls! {
4041
}
4142

4243
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
43-
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
44+
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
4445

4546
#[derive(Debug)]
4647
pub struct ConstEvalErr<'tcx> {

src/librustc/mir/interpret/value.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt;
77

88
use crate::ty::{
99
layout::{HasDataLayout, Size},
10-
Ty,
10+
ParamEnv, Ty, TyCtxt,
1111
};
1212

1313
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
@@ -66,6 +66,32 @@ impl<'tcx> ConstValue<'tcx> {
6666
ConstValue::Scalar(val) => Some(val),
6767
}
6868
}
69+
70+
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
71+
self.try_to_scalar()?.to_bits(size).ok()
72+
}
73+
74+
pub fn try_to_bits_for_ty(
75+
&self,
76+
tcx: TyCtxt<'tcx>,
77+
param_env: ParamEnv<'tcx>,
78+
ty: Ty<'tcx>,
79+
) -> Option<u128> {
80+
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
81+
self.try_to_bits(size)
82+
}
83+
84+
pub fn from_bool(b: bool) -> Self {
85+
ConstValue::Scalar(Scalar::from_bool(b))
86+
}
87+
88+
pub fn from_u64(i: u64) -> Self {
89+
ConstValue::Scalar(Scalar::from_u64(i))
90+
}
91+
92+
pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self {
93+
ConstValue::Scalar(Scalar::from_machine_usize(cx, i))
94+
}
6995
}
7096

7197
/// A `Scalar` represents an immediate, primitive value existing outside of a
@@ -287,6 +313,11 @@ impl<'tcx, Tag> Scalar<Tag> {
287313
Scalar::Raw { data: i as u128, size: 8 }
288314
}
289315

316+
#[inline]
317+
pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self {
318+
Self::from_uint(i, cx.data_layout().pointer_size)
319+
}
320+
290321
#[inline]
291322
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
292323
let i = i.into();

src/librustc/ty/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,10 +2380,10 @@ impl<'tcx> AdtDef {
23802380
let repr_type = self.repr.discr_type();
23812381
match tcx.const_eval_poly(expr_did) {
23822382
Ok(val) => {
2383-
// FIXME: Find the right type and use it instead of `val.ty` here
2384-
if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
2383+
let ty = repr_type.to_ty(tcx);
2384+
if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
23852385
trace!("discriminants: {} ({:?})", b, repr_type);
2386-
Some(Discr { val: b, ty: val.ty })
2386+
Some(Discr { val: b, ty })
23872387
} else {
23882388
info!("invalid enum discriminant: {:#?}", val);
23892389
crate::mir::interpret::struct_error(

src/librustc/ty/sty.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2471,7 +2471,9 @@ impl<'tcx> Const<'tcx> {
24712471

24722472
// try to resolve e.g. associated constants to their definition on an impl, and then
24732473
// evaluate the const.
2474-
tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
2474+
tcx.const_eval_resolve(param_env, did, substs, promoted, None)
2475+
.ok()
2476+
.map(|val| tcx.mk_const(Const { val: ConstKind::Value(val), ty: self.ty }))
24752477
};
24762478

24772479
match self.val {

src/librustc_codegen_llvm/consts.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,9 @@ pub fn codegen_static_initializer(
7878
cx: &CodegenCx<'ll, 'tcx>,
7979
def_id: DefId,
8080
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
81-
let static_ = cx.tcx.const_eval_poly(def_id)?;
82-
83-
let alloc = match static_.val {
84-
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) if offset.bytes() == 0 => alloc,
85-
_ => bug!("static const eval returned {:#?}", static_),
81+
let alloc = match cx.tcx.const_eval_poly(def_id)? {
82+
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
83+
val => bug!("static const eval returned {:#?}", val),
8684
};
8785
Ok((const_alloc_to_llvm(cx, alloc), alloc))
8886
}

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
193193
.tcx
194194
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
195195
.unwrap();
196-
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
196+
let const_ = ty::Const { val: ty::ConstKind::Value(ty_name), ty: ret_ty };
197+
OperandRef::from_const(self, &const_).immediate_or_packed_pair(self)
197198
}
198199
"init" => {
199200
let ty = substs.type_at(0);

src/librustc_codegen_ssa/mir/constant.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
3030
}
3131
_ => {
3232
let val = self.eval_mir_constant(constant)?;
33-
Ok(OperandRef::from_const(bx, val))
33+
Ok(OperandRef::from_const(bx, &val))
3434
}
3535
}
3636
}
@@ -45,6 +45,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
4545
self.cx
4646
.tcx()
4747
.const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
48+
.map(|val| {
49+
self.cx.tcx().mk_const(ty::Const {
50+
val: ty::ConstKind::Value(val),
51+
ty: constant.literal.ty,
52+
})
53+
})
4854
.map_err(|err| {
4955
if promoted.is_none() {
5056
self.cx

src/librustc_codegen_ssa/mir/operand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
6666

6767
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
6868
bx: &mut Bx,
69-
val: &'tcx ty::Const<'tcx>,
69+
val: &ty::Const<'tcx>,
7070
) -> Self {
7171
let layout = bx.layout_of(val.ty);
7272

src/librustc_mir/const_eval.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ pub(crate) fn const_field<'tcx>(
4040
let field = ecx.operand_field(down, field.index() as u64).unwrap();
4141
// and finally move back to the const world, always normalizing because
4242
// this is not called for statics.
43-
op_to_const(&ecx, field)
43+
let val = op_to_const(&ecx, field);
44+
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
4445
}
4546

4647
pub(crate) fn const_caller_location<'tcx>(
@@ -84,7 +85,8 @@ pub(crate) fn destructure_const<'tcx>(
8485
let down = ecx.operand_downcast(op, variant).unwrap();
8586
let fields_iter = (0..field_count).map(|i| {
8687
let field_op = ecx.operand_field(down, i).unwrap();
87-
op_to_const(&ecx, field_op)
88+
let val = op_to_const(&ecx, field_op);
89+
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: field_op.layout.ty })
8890
});
8991
let fields = tcx.arena.alloc_from_iter(fields_iter);
9092

src/librustc_mir/const_eval/eval_queries.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
9797
pub(super) fn op_to_const<'tcx>(
9898
ecx: &CompileTimeEvalContext<'_, 'tcx>,
9999
op: OpTy<'tcx>,
100-
) -> &'tcx ty::Const<'tcx> {
100+
) -> ConstValue<'tcx> {
101101
// We do not have value optimizations for everything.
102102
// Only scalars and slices, since they are very common.
103103
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
@@ -144,7 +144,7 @@ pub(super) fn op_to_const<'tcx>(
144144
ConstValue::Scalar(Scalar::zst())
145145
}
146146
};
147-
let val = match immediate {
147+
match immediate {
148148
Ok(mplace) => to_const_value(mplace),
149149
// see comment on `let try_as_immediate` above
150150
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
@@ -166,8 +166,7 @@ pub(super) fn op_to_const<'tcx>(
166166
let len: usize = len.try_into().unwrap();
167167
ConstValue::Slice { data, start, end: start + len }
168168
}
169-
};
170-
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
169+
}
171170
}
172171

173172
fn validate_and_turn_into_const<'tcx>(
@@ -195,13 +194,10 @@ fn validate_and_turn_into_const<'tcx>(
195194
// whether they become immediates.
196195
if is_static || cid.promoted.is_some() {
197196
let ptr = mplace.ptr.assert_ptr();
198-
Ok(tcx.mk_const(ty::Const {
199-
val: ty::ConstKind::Value(ConstValue::ByRef {
200-
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
201-
offset: ptr.offset,
202-
}),
203-
ty: mplace.layout.ty,
204-
}))
197+
Ok(ConstValue::ByRef {
198+
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
199+
offset: ptr.offset,
200+
})
205201
} else {
206202
Ok(op_to_const(&ecx, mplace.into()))
207203
}

src/librustc_mir/interpret/eval_context.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
756756
pub(super) fn const_eval(
757757
&self,
758758
gid: GlobalId<'tcx>,
759+
ty: Ty<'tcx>,
759760
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
760761
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
761762
// and thus don't care about the parameter environment. While we could just use
@@ -777,7 +778,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
777778
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
778779
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
779780
// `ecx.const_eval`.
780-
self.eval_const_to_op(val, None)
781+
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
782+
self.eval_const_to_op(&const_, None)
781783
}
782784

783785
pub fn const_eval_raw(

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,15 @@ crate fn eval_nullary_intrinsic<'tcx>(
4848
param_env: ty::ParamEnv<'tcx>,
4949
def_id: DefId,
5050
substs: SubstsRef<'tcx>,
51-
) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
51+
) -> InterpResult<'tcx, ConstValue<'tcx>> {
5252
let tp_ty = substs.type_at(0);
5353
let name = tcx.item_name(def_id);
5454
Ok(match name {
5555
sym::type_name => {
5656
let alloc = type_name::alloc_type_name(tcx, tp_ty);
57-
tcx.mk_const(ty::Const {
58-
val: ty::ConstKind::Value(ConstValue::Slice {
59-
data: alloc,
60-
start: 0,
61-
end: alloc.len(),
62-
}),
63-
ty: tcx.mk_static_str(),
64-
})
57+
ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
6558
}
66-
sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
59+
sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)),
6760
sym::size_of | sym::min_align_of | sym::pref_align_of => {
6861
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
6962
let n = match name {
@@ -72,11 +65,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
7265
sym::size_of => layout.size.bytes(),
7366
_ => bug!(),
7467
};
75-
ty::Const::from_usize(tcx, n)
76-
}
77-
sym::type_id => {
78-
ty::Const::from_bits(tcx, tcx.type_id_hash(tp_ty).into(), param_env.and(tcx.types.u64))
68+
ConstValue::from_machine_usize(&tcx, n)
7969
}
70+
sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()),
8071
other => bug!("`{}` is not a zero arg intrinsic", other),
8172
})
8273
}
@@ -119,7 +110,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
119110
| sym::type_id
120111
| sym::type_name => {
121112
let gid = GlobalId { instance, promoted: None };
122-
let val = self.const_eval(gid)?;
113+
let ty = instance.ty_env(*self.tcx, self.param_env);
114+
let val = self.const_eval(gid, ty)?;
123115
self.copy_op(val, dest)?;
124116
}
125117

src/librustc_mir/interpret/operand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
518518
/// "universe" (param_env).
519519
crate fn eval_const_to_op(
520520
&self,
521-
val: &'tcx ty::Const<'tcx>,
521+
val: &ty::Const<'tcx>,
522522
layout: Option<TyLayout<'tcx>>,
523523
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
524524
let tag_scalar = |scalar| match scalar {
@@ -536,7 +536,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
536536
// potentially requiring the current static to be evaluated again. This is not a
537537
// problem here, because we are building an operand which means an actual read is
538538
// happening.
539-
return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
539+
return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?);
540540
}
541541
ty::ConstKind::Infer(..)
542542
| ty::ConstKind::Bound(..)

src/librustc_mir/monomorphize/collector.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ fn collect_items_rec<'tcx>(
357357
recursion_depth_reset = None;
358358

359359
if let Ok(val) = tcx.const_eval_poly(def_id) {
360-
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
360+
collect_const_value(tcx, val, &mut neighbors);
361361
}
362362
}
363363
MonoItem::Fn(instance) => {
@@ -971,7 +971,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
971971
let def_id = self.tcx.hir().local_def_id(item.hir_id);
972972

973973
if let Ok(val) = self.tcx.const_eval_poly(def_id) {
974-
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
974+
collect_const_value(self.tcx, val, &mut self.output);
975975
}
976976
}
977977
hir::ItemKind::Fn(..) => {
@@ -1185,18 +1185,10 @@ fn collect_const<'tcx>(
11851185
tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant);
11861186

11871187
match substituted_constant.val {
1188-
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) => {
1189-
collect_miri(tcx, ptr.alloc_id, output)
1190-
}
1191-
ty::ConstKind::Value(ConstValue::Slice { data: alloc, start: _, end: _ })
1192-
| ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) => {
1193-
for &((), id) in alloc.relocations().values() {
1194-
collect_miri(tcx, id, output);
1195-
}
1196-
}
1188+
ty::ConstKind::Value(val) => collect_const_value(tcx, val, output),
11971189
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
11981190
match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
1199-
Ok(val) => collect_const(tcx, val, param_substs, output),
1191+
Ok(val) => collect_const_value(tcx, val, output),
12001192
Err(ErrorHandled::Reported) => {}
12011193
Err(ErrorHandled::TooGeneric) => {
12021194
span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
@@ -1206,3 +1198,19 @@ fn collect_const<'tcx>(
12061198
_ => {}
12071199
}
12081200
}
1201+
1202+
fn collect_const_value<'tcx>(
1203+
tcx: TyCtxt<'tcx>,
1204+
value: ConstValue<'tcx>,
1205+
output: &mut Vec<MonoItem<'tcx>>,
1206+
) {
1207+
match value {
1208+
ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),
1209+
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
1210+
for &((), id) in alloc.relocations().values() {
1211+
collect_miri(tcx, id, output);
1212+
}
1213+
}
1214+
_ => {}
1215+
}
1216+
}

src/librustc_mir_build/hair/cx/expr.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,17 @@ fn make_mirror_unadjusted<'a, 'tcx>(
418418
None,
419419
Some(span),
420420
) {
421-
Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()),
421+
Ok(cv) => {
422+
if let Some(count) = cv.try_to_bits_for_ty(
423+
cx.tcx,
424+
ty::ParamEnv::reveal_all(),
425+
cx.tcx.types.usize,
426+
) {
427+
count as u64
428+
} else {
429+
bug!("repeat count constant value can't be converted to usize");
430+
}
431+
}
422432
Err(ErrorHandled::Reported) => 0,
423433
Err(ErrorHandled::TooGeneric) => {
424434
let span = cx.tcx.def_span(def_id);

0 commit comments

Comments
 (0)