X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_mir%2Finterpret%2Feval_context.rs;h=b2db0fea3d09a7afdb7ff1c85edebe080963e65c;hb=db2978a73cc4ab71c8839e70d12bc87d5279e632;hp=9a76a36ef2293057d08793a0ba91bd69db0af64c;hpb=96530344ef951c79e07cad69cf65eddb876b0e2d;p=rust.git
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 9a76a36ef22..b2db0fea3d0 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1,3 +1,4 @@
+use std::cell::Cell;
use std::fmt::Write;
use std::mem;
@@ -42,7 +43,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
pub(crate) stack: Vec>,
/// A cache for deduplicating vtables
- pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
+ pub(super) vtables: FxHashMap<(Ty<'tcx>, Option>), AllocId>,
}
/// A stack frame.
@@ -76,6 +77,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
/// `None` represents a local that is currently dead, while a live local
/// can either directly contain `Scalar` or refer to some part of an `Allocation`.
pub locals: IndexVec>,
+ pub local_layouts: IndexVec>>>,
////////////////////////////////////////////////////////////////////////////////
// Current position within the function
@@ -214,11 +216,21 @@ pub(super) fn mir(&self) -> &'mir mir::Mir<'tcx> {
self.frame().mir
}
- pub fn substs(&self) -> &'tcx Substs<'tcx> {
- if let Some(frame) = self.stack.last() {
- frame.instance.substs
- } else {
- Substs::empty()
+ pub(super) fn subst_and_normalize_erasing_regions>(
+ &self,
+ substs: T,
+ ) -> EvalResult<'tcx, T> {
+ match self.stack.last() {
+ Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions(
+ frame.instance.substs,
+ self.param_env,
+ &substs,
+ )),
+ None => if substs.needs_subst() {
+ err!(TooGeneric).into()
+ } else {
+ Ok(substs)
+ },
}
}
@@ -228,13 +240,9 @@ pub(super) fn resolve(
substs: &'tcx Substs<'tcx>
) -> EvalResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def_id, substs);
- trace!("substs: {:#?}", self.substs());
trace!("param_env: {:#?}", self.param_env);
- let substs = self.tcx.subst_and_normalize_erasing_regions(
- self.substs(),
- self.param_env,
- &substs,
- );
+ let substs = self.subst_and_normalize_erasing_regions(substs)?;
+ trace!("substs: {:#?}", substs);
ty::Instance::resolve(
*self.tcx,
self.param_env,
@@ -274,6 +282,20 @@ pub fn load_mir(
}
}
+ pub fn monomorphize_in_frame + Subst<'tcx>>(
+ &self,
+ t: T,
+ ) -> EvalResult<'tcx, T> {
+ match self.stack.last() {
+ Some(frame) => Ok(self.monomorphize(t, frame.instance.substs)),
+ None => if t.needs_subst() {
+ err!(TooGeneric).into()
+ } else {
+ Ok(t)
+ },
+ }
+ }
+
pub fn monomorphize + Subst<'tcx>>(
&self,
t: T,
@@ -290,9 +312,15 @@ pub fn layout_of_local(
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
local: mir::Local
) -> EvalResult<'tcx, TyLayout<'tcx>> {
- let local_ty = frame.mir.local_decls[local].ty;
- let local_ty = self.monomorphize(local_ty, frame.instance.substs);
- self.layout_of(local_ty)
+ let cell = &frame.local_layouts[local];
+ if cell.get().is_none() {
+ let local_ty = frame.mir.local_decls[local].ty;
+ let local_ty = self.monomorphize(local_ty, frame.instance.substs);
+ let layout = self.layout_of(local_ty)?;
+ cell.set(Some(layout));
+ }
+
+ Ok(cell.get().unwrap())
}
pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate> {
@@ -426,6 +454,7 @@ pub fn push_stack_frame(
// empty local array, we fill it in below, after we are inside the stack frame and
// all methods actually know about the frame
locals: IndexVec::new(),
+ local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
span,
instance,
stmt: 0,
@@ -464,11 +493,11 @@ pub fn push_stack_frame(
},
}
// Finally, properly initialize all those that still have the dummy value
- for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+ for (idx, local) in locals.iter_enumerated_mut() {
match *local {
LocalValue::Live(_) => {
// This needs to be peoperly initialized.
- let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?;
+ let layout = self.layout_of_local(self.frame(), idx)?;
*local = LocalValue::Live(self.uninit_operand(layout)?);
}
LocalValue::Dead => {