[const-prop] Replace eval_place() with use of InterpCx
This commit is contained in:
parent
59367b074f
commit
bc17936c8a
9 changed files with 43 additions and 57 deletions
|
|
@ -389,6 +389,14 @@ pub enum UnsupportedOpInfo<'tcx> {
|
|||
/// Free-form case. Only for errors that are never caught!
|
||||
Unsupported(String),
|
||||
|
||||
/// Error used by the `ConstProp` pass when an attempt is made
|
||||
/// to read an uninitialized local.
|
||||
UninitializedLocal,
|
||||
|
||||
/// Error used by the `ConstProp` pass to prevent reading statics
|
||||
/// while evaluating `const` items.
|
||||
ReadOfStaticInConst,
|
||||
|
||||
// -- Everything below is not categorized yet --
|
||||
FunctionAbiMismatch(Abi, Abi),
|
||||
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
|
||||
|
|
@ -511,6 +519,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
|
|||
addresses, e.g., comparing pointers into different allocations"),
|
||||
DeadLocal =>
|
||||
write!(f, "tried to access a dead local variable"),
|
||||
UninitializedLocal =>
|
||||
write!(f, "tried to access an uninitialized local variable"),
|
||||
DerefFunctionPointer =>
|
||||
write!(f, "tried to dereference a function pointer"),
|
||||
ExecuteMemory =>
|
||||
|
|
@ -552,6 +562,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
|
|||
not a power of two"),
|
||||
Unsupported(ref msg) =>
|
||||
write!(f, "{}", msg),
|
||||
ReadOfStaticInConst =>
|
||||
write!(f, "tried to read from a static during const evaluation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,8 +134,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
|
|||
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
|
||||
match self.value {
|
||||
LocalValue::Dead => throw_unsup!(DeadLocal),
|
||||
LocalValue::Uninitialized =>
|
||||
bug!("The type checker should prevent reading from a never-written local"),
|
||||
LocalValue::Uninitialized => throw_unsup!(UninitializedLocal),
|
||||
LocalValue::Live(val) => Ok(val),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
// Evaluate a place with the goal of reading from it. This lets us sometimes
|
||||
// avoid allocations.
|
||||
pub(super) fn eval_place_to_op(
|
||||
pub fn eval_place_to_op(
|
||||
&self,
|
||||
place: &mir::Place<'tcx>,
|
||||
layout: Option<TyLayout<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -597,6 +597,15 @@ where
|
|||
}
|
||||
|
||||
StaticKind::Static => {
|
||||
//if the first frame on the stack isn't a static item, then we shouldn't
|
||||
//eval any static places (unless -Z unleash-the-miri-inside-of-you is on)
|
||||
if let ty::InstanceDef::Item(item_def_id) = self.stack[0].instance.def {
|
||||
if !self.tcx.is_static(item_def_id) &&
|
||||
!self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
|
||||
trace!("eval_static_to_mplace: can't eval static in constant");
|
||||
throw_unsup!(ReadOfStaticInConst);
|
||||
}
|
||||
}
|
||||
let ty = place_static.ty;
|
||||
assert!(!ty.needs_subst());
|
||||
let layout = self.layout_of(ty)?;
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ use std::cell::Cell;
|
|||
use rustc::hir::def::DefKind;
|
||||
use rustc::mir::{
|
||||
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
|
||||
Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
|
||||
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
|
||||
Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
|
||||
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp,
|
||||
SourceScope, SourceScopeLocalData, LocalDecl,
|
||||
};
|
||||
use rustc::mir::visit::{
|
||||
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
|
||||
};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
|
||||
use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
|
||||
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc::ty::subst::InternalSubsts;
|
||||
|
|
@ -282,53 +282,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
|
||||
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
|
||||
trace!("eval_place(place={:?})", place);
|
||||
let mut eval = match place.base {
|
||||
PlaceBase::Local(loc) => self.get_const(loc).clone()?,
|
||||
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
|
||||
let generics = self.tcx.generics_of(self.source.def_id());
|
||||
if generics.requires_monomorphization(self.tcx) {
|
||||
// FIXME: can't handle code with generics
|
||||
return None;
|
||||
}
|
||||
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
|
||||
let instance = Instance::new(self.source.def_id(), substs);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: Some(promoted),
|
||||
};
|
||||
let res = self.use_ecx(source_info, |this| {
|
||||
this.ecx.const_eval_raw(cid)
|
||||
})?;
|
||||
trace!("evaluated promoted {:?} to {:?}", promoted, res);
|
||||
res.into()
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
for (i, elem) in place.projection.iter().enumerate() {
|
||||
let proj_base = &place.projection[..i];
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Field(field, _) => {
|
||||
trace!("field proj on {:?}", proj_base);
|
||||
eval = self.use_ecx(source_info, |this| {
|
||||
this.ecx.operand_field(eval, field.index() as u64)
|
||||
})?;
|
||||
},
|
||||
ProjectionElem::Deref => {
|
||||
trace!("processing deref");
|
||||
eval = self.use_ecx(source_info, |this| {
|
||||
this.ecx.deref_operand(eval)
|
||||
})?.into();
|
||||
}
|
||||
// We could get more projections by using e.g., `operand_projection`,
|
||||
// but we do not even have the stack frame set up properly so
|
||||
// an `Index` projection would throw us off-track.
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
||||
Some(eval)
|
||||
self.use_ecx(source_info, |this| {
|
||||
this.ecx.eval_place_to_op(place, None)
|
||||
})
|
||||
}
|
||||
|
||||
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn main() {
|
|||
// assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
|
||||
// }
|
||||
// bb1: {
|
||||
// _1 = (*_2)[_6];
|
||||
// _1 = const 2u32;
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ struct Sum<A,B>(A,B);
|
|||
|
||||
impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
|
||||
const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
|
||||
//~| ERROR any use of this value will cause an error
|
||||
}
|
||||
|
||||
fn foo<T>(_: T) -> &'static u8 {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,21 @@ LL | const MAX: u8 = A::MAX + B::MAX;
|
|||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
error[E0080]: evaluation of constant expression failed
|
||||
--> $DIR/issue-50814.rs:17:5
|
||||
--> $DIR/issue-50814.rs:18:5
|
||||
|
|
||||
LL | &Sum::<U8,U8>::MAX
|
||||
| ^-----------------
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/issue-50814.rs:13:21
|
||||
|
|
||||
LL | const MAX: u8 = A::MAX + B::MAX;
|
||||
| ----------------^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| attempt to add with overflow
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ LL | static B: [u32; 1] = [0; A.len()];
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0013`.
|
||||
Some errors have detailed explanations: E0013, E0080.
|
||||
For more information about an error, try `rustc --explain E0013`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue