use std::fmt::Write;
use std::mem;
-use rustc::hir::def::DefKind;
-use rustc::hir::def_id::DefId;
use rustc::ich::StableHashingContext;
use rustc::mir;
use rustc::mir::interpret::{
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
-use syntax::source_map::{self, Span, DUMMY_SP};
+use rustc_span::source_map::{self, Span, DUMMY_SP};
use super::{
- Immediate, MPlaceTy, Machine, MemPlace, Memory, OpTy, Operand, Place, PlaceTy,
+ Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
ScalarMaybeUndef, StackPopInfo,
};
&mut self,
) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
match self.value {
- LocalValue::Dead => throw_unsup!(DeadLocal),
- LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
+ LocalValue::Dead => {
+ throw_unsup!(DeadLocal)
+ }
+ LocalValue::Live(Operand::Indirect(mplace)) => {
+ Ok(Err(mplace))
+ }
ref mut local @ LocalValue::Live(Operand::Immediate(_))
- | ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)),
+ | ref mut local @ LocalValue::Uninitialized => {
+ Ok(Ok(local))
+ }
}
}
}
/// This can fail to provide an answer for extern types.
pub(super) fn size_and_align_of(
&self,
- metadata: Option<Scalar<M::PointerTag>>,
+ metadata: MemPlaceMeta<M::PointerTag>,
layout: TyLayout<'tcx>,
) -> InterpResult<'tcx, Option<(Size, Align)>> {
if !layout.is_unsized() {
Ok(Some((size, align)))
}
ty::Dynamic(..) => {
- let vtable = metadata.expect("dyn trait fat ptr must have vtable");
+ let vtable = metadata.unwrap_meta();
// Read size and align from vtable (already checks size).
Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
}
ty::Slice(_) | ty::Str => {
- let len =
- metadata.expect("slice fat ptr must have length").to_machine_usize(self)?;
+ let len = metadata.unwrap_meta().to_machine_usize(self)?;
let elem = layout.field(self, 0)?;
// Make sure the slice is not too big.
&self,
gid: GlobalId<'tcx>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
- let val = if self.tcx.is_static(gid.instance.def_id()) {
- self.tcx.const_eval_poly(gid.instance.def_id())?
- } else if let Some(promoted) = gid.promoted {
- self.tcx.const_eval_promoted(gid.instance, promoted)?
+ // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
+ // and thus don't care about the parameter environment. While we could just use
+ // `self.param_env`, that would mean we invoke the query to evaluate the static
+ // with different parameter environments, thus causing the static to be evaluated
+ // multiple times.
+ let param_env = if self.tcx.is_static(gid.instance.def_id()) {
+ ty::ParamEnv::reveal_all()
} else {
- self.tcx.const_eval_instance(self.param_env, gid.instance, Some(self.tcx.span))?
+ self.param_env
};
+ let val = if let Some(promoted) = gid.promoted {
+ self.tcx.const_eval_promoted(param_env, gid.instance, promoted)?
+ } else {
+ self.tcx.const_eval_instance(param_env, gid.instance, Some(self.tcx.span))?
+ };
+
// Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
" by align({}){} ref:",
mplace.align.bytes(),
match mplace.meta {
- Some(meta) => format!(" meta({:?})", meta),
- None => String::new(),
+ MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
+ MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
}
)
.unwrap();