Skip to content

Commit 235a6b7

Browse files
committed
Expose const -> op functions that don't allow violiting const eval invariants
1 parent eac0908 commit 235a6b7

File tree

3 files changed

+37
-46
lines changed

3 files changed

+37
-46
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ pub fn const_field<'a, 'tcx>(
476476
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
477477
let result = (|| {
478478
// get the operand again
479-
let op = ecx.lazy_const_to_op(ty::LazyConst::Evaluated(value), value.ty)?;
479+
let op = ecx.const_to_op(value, None)?;
480480
// downcast
481481
let down = match variant {
482482
None => op,
@@ -502,7 +502,7 @@ pub fn const_variant_index<'a, 'tcx>(
502502
) -> EvalResult<'tcx, VariantIdx> {
503503
trace!("const_variant_index: {:?}", val);
504504
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
505-
let op = ecx.lazy_const_to_op(ty::LazyConst::Evaluated(val), val.ty)?;
505+
let op = ecx.const_to_op(val, None)?;
506506
Ok(ecx.read_discriminant(op)?.1)
507507
}
508508

src/librustc_mir/interpret/operand.rs

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc::mir::interpret::{
1212
EvalResult, EvalErrorKind,
1313
};
1414
use super::{
15-
EvalContext, Machine, AllocMap, Allocation, AllocationExtra,
15+
EvalContext, Machine,
1616
MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind,
1717
};
1818
pub use rustc::mir::interpret::ScalarMaybeUndef;
@@ -545,14 +545,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
545545
Move(ref place) =>
546546
self.eval_place_to_op(place, layout)?,
547547

548-
Constant(ref constant) => {
549-
let layout = from_known_layout(layout, || {
550-
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx))?;
551-
self.layout_of(ty)
552-
})?;
553-
let op = self.const_value_to_op(*constant.literal)?;
554-
OpTy { op, layout }
555-
}
548+
Constant(ref constant) => self.lazy_const_to_op(*constant.literal, layout)?,
556549
};
557550
trace!("{:?}: {:?}", mir_op, *op);
558551
Ok(op)
@@ -568,38 +561,55 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
568561
.collect()
569562
}
570563

571-
// Used when Miri runs into a constant, and (indirectly through lazy_const_to_op) by CTFE.
572-
fn const_value_to_op(
564+
// Used when Miri runs into a constant, and by CTFE.
565+
pub fn lazy_const_to_op(
573566
&self,
574567
val: ty::LazyConst<'tcx>,
575-
) -> EvalResult<'tcx, Operand<M::PointerTag>> {
576-
trace!("const_value_to_op: {:?}", val);
577-
let val = match val {
568+
layout: Option<TyLayout<'tcx>>,
569+
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
570+
trace!("const_to_op: {:?}", val);
571+
match val {
578572
ty::LazyConst::Unevaluated(def_id, substs) => {
579573
let instance = self.resolve(def_id, substs)?;
580-
return Ok(*OpTy::from(self.const_eval_raw(GlobalId {
574+
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
581575
instance,
582576
promoted: None,
583577
})?));
584578
},
585-
ty::LazyConst::Evaluated(c) => c,
586-
};
587-
match val.val {
579+
ty::LazyConst::Evaluated(c) => self.const_to_op(c, layout),
580+
}
581+
}
582+
583+
// Used when Miri runs into a constant, and (indirectly through lazy_const_to_op) by CTFE.
584+
pub fn const_to_op(
585+
&self,
586+
val: ty::Const<'tcx>,
587+
layout: Option<TyLayout<'tcx>>,
588+
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
589+
let layout = from_known_layout(layout, || {
590+
let ty = self.monomorphize(val.ty)?;
591+
self.layout_of(ty)
592+
})?;
593+
let op = match val.val {
588594
ConstValue::ByRef(id, alloc, offset) => {
589595
// We rely on mutability being set correctly in that allocation to prevent writes
590596
// where none should happen -- and for `static mut`, we copy on demand anyway.
591-
Ok(Operand::Indirect(
597+
Operand::Indirect(
592598
MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
593-
).with_default_tag())
599+
).with_default_tag()
594600
},
595601
ConstValue::Slice(a, b) =>
596-
Ok(Operand::Immediate(Immediate::ScalarPair(
602+
Operand::Immediate(Immediate::ScalarPair(
597603
a.into(),
598604
Scalar::from_uint(b, self.tcx.data_layout.pointer_size).into(),
599-
)).with_default_tag()),
605+
)).with_default_tag(),
600606
ConstValue::Scalar(x) =>
601-
Ok(Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag()),
602-
}
607+
Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(),
608+
};
609+
Ok(OpTy {
610+
op,
611+
layout,
612+
})
603613
}
604614

605615
/// Read discriminant, return the runtime value as well as the variant index.
@@ -699,23 +709,4 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
699709
}
700710
})
701711
}
702-
703-
}
704-
705-
impl<'a, 'mir, 'tcx, M> EvalContext<'a, 'mir, 'tcx, M>
706-
where
707-
M: Machine<'a, 'mir, 'tcx, PointerTag=()>,
708-
// FIXME: Working around https://github.com/rust-lang/rust/issues/24159
709-
M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<(), M::AllocExtra>)>,
710-
M::AllocExtra: AllocationExtra<(), M::MemoryExtra>,
711-
{
712-
// FIXME: CTFE should use allocations, then we can remove this.
713-
pub(crate) fn lazy_const_to_op(
714-
&self,
715-
cnst: ty::LazyConst<'tcx>,
716-
ty: ty::Ty<'tcx>,
717-
) -> EvalResult<'tcx, OpTy<'tcx>> {
718-
let op = self.const_value_to_op(cnst)?;
719-
Ok(OpTy { op, layout: self.layout_of(ty)? })
720-
}
721712
}

src/librustc_mir/transform/const_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
253253
source_info: SourceInfo,
254254
) -> Option<Const<'tcx>> {
255255
self.ecx.tcx.span = source_info.span;
256-
match self.ecx.lazy_const_to_op(*c.literal, c.ty) {
256+
match self.ecx.lazy_const_to_op(*c.literal, None) {
257257
Ok(op) => {
258258
Some((op, c.span))
259259
},

0 commit comments

Comments
 (0)