// avoid allocations.
pub(super) fn eval_place_to_op(
&self,
- mir_place: &mir::Place<'tcx>,
+ place: &mir::Place<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
use rustc::mir::PlaceBase;
- mir_place.iterate(|place_base, place_projection| {
- let mut op = match place_base {
- PlaceBase::Local(mir::RETURN_PLACE) =>
- throw_unsup!(ReadFromReturnPointer),
- PlaceBase::Local(local) => {
- // Do not use the layout passed in as argument if the base we are looking at
- // here is not the entire place.
- // FIXME use place_projection.is_empty() when is available
- let layout = if mir_place.projection.is_none() {
- layout
- } else {
- None
- };
-
- self.access_local(self.frame(), *local, layout)?
- }
- PlaceBase::Static(place_static) => {
- self.eval_static_to_mplace(place_static)?.into()
- }
- };
+ let mut op = match &place.base {
+ PlaceBase::Local(mir::RETURN_PLACE) =>
+ throw_unsup!(ReadFromReturnPointer),
+ PlaceBase::Local(local) => {
+ // Do not use the layout passed in as argument if the base we are looking at
+ // here is not the entire place.
+ // FIXME use place_projection.is_empty() when is available
+ let layout = if place.projection.is_empty() {
+ layout
+ } else {
+ None
+ };
- for proj in place_projection {
- op = self.operand_projection(op, &proj.elem)?
+ self.access_local(self.frame(), *local, layout)?
+ }
+ PlaceBase::Static(place_static) => {
+ self.eval_static_to_mplace(&place_static)?.into()
}
+ };
- trace!("eval_place_to_op: got {:?}", *op);
- Ok(op)
- })
+ for elem in place.projection.iter() {
+ op = self.operand_projection(op, elem)?
+ }
+
+ trace!("eval_place_to_op: got {:?}", *op);
+ Ok(op)
}
/// Evaluate the operand, returning a place where you can then find the data.
Move(ref place) =>
self.eval_place_to_op(place, layout)?,
- Constant(ref constant) => self.eval_const_to_op(constant.literal, layout)?,
+ Constant(ref constant) => {
+ let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal);
+ self.eval_const_to_op(val, layout)?
+ }
};
trace!("{:?}: {:?}", mir_op, *op);
Ok(op)
// Used when the miri-engine runs into a constant and for extracting information from constants
// in patterns via the `const_eval` module
+ /// The `val` and `layout` are assumed to already be in our interpreter
+ /// "universe" (param_env).
crate fn eval_const_to_op(
&self,
val: &'tcx ty::Const<'tcx>,
// Early-return cases.
match val.val {
ConstValue::Param(_) =>
- // FIXME(oli-obk): try to monomorphize
throw_inval!(TooGeneric),
ConstValue::Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
}
// Other cases need layout.
let layout = from_known_layout(layout, || {
- self.layout_of(self.monomorphize(val.ty)?)
+ self.layout_of(val.ty)
})?;
let op = match val.val {
ConstValue::ByRef { alloc, offset } => {
// post-process
Ok(match *discr_kind {
layout::DiscriminantKind::Tag => {
- let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
- Ok(raw_discr) => raw_discr,
- Err(_) =>
- throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag())),
- };
+ let bits_discr = raw_discr
+ .not_undef()
+ .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
+ .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?;
let real_discr = if discr_val.layout.ty.is_signed() {
// going from layout tag type to typeck discriminant type
// requires first sign extending with the layout discriminant