diff --git a/src/interpreter.rs b/src/interpreter.rs
index b9c9160015ea..a7a1ffb27b60 100644
--- a/src/interpreter.rs
+++ b/src/interpreter.rs
@@ -10,7 +10,7 @@ use rustc::ty::subst::{self, Subst, Substs};
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::DefIdMap;
use std::cell::RefCell;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use std::{iter, mem};
use syntax::ast;
@@ -23,7 +23,7 @@ use primval::{self, PrimVal};
const TRACE_EXECUTION: bool = false;
-struct Interpreter<'a, 'tcx: 'a> {
+struct GlobalEvalContext<'a, 'tcx: 'a> {
/// The results of the type checker, from rustc.
tcx: &'a TyCtxt<'tcx>,
@@ -36,9 +36,6 @@ struct Interpreter<'a, 'tcx: 'a> {
/// The virtual memory system.
memory: Memory,
- /// The virtual call stack.
- stack: Vec>,
-
/// Another stack containing the type substitutions for the current function invocation. It
/// exists separately from `stack` because it must contain the `Substs` for a function while
/// *creating* the `Frame` for that same function.
@@ -51,6 +48,26 @@ struct Interpreter<'a, 'tcx: 'a> {
name_stack: Vec<(DefId, &'tcx Substs<'tcx>, codemap::Span)>,
}
+struct FnEvalContext<'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> {
+ gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
+
+ /// The virtual call stack.
+ stack: Vec>,
+}
+
+impl<'a, 'b, 'mir, 'tcx> Deref for FnEvalContext<'a, 'b, 'mir, 'tcx> {
+ type Target = GlobalEvalContext<'b, 'tcx>;
+ fn deref(&self) -> &Self::Target {
+ self.gecx
+ }
+}
+
+impl<'a, 'b, 'mir, 'tcx> DerefMut for FnEvalContext<'a, 'b, 'mir, 'tcx> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.gecx
+ }
+}
+
/// A stack frame.
struct Frame<'a, 'tcx: 'a> {
/// The MIR for the function called on this frame.
@@ -106,18 +123,26 @@ enum TerminatorTarget {
Return,
}
-impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
+impl<'a, 'tcx> GlobalEvalContext<'a, 'tcx> {
fn new(tcx: &'a TyCtxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
- Interpreter {
+ GlobalEvalContext {
tcx: tcx,
mir_map: mir_map,
mir_cache: RefCell::new(DefIdMap()),
memory: Memory::new(),
- stack: Vec::new(),
substs_stack: Vec::new(),
name_stack: Vec::new(),
}
}
+}
+
+impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
+ fn new(gecx: &'a mut GlobalEvalContext<'b, 'tcx>) -> Self {
+ FnEvalContext {
+ gecx: gecx,
+ stack: Vec::new(),
+ }
+ }
fn maybe_report(&self, span: codemap::Span, r: EvalResult) -> EvalResult {
if let Err(ref e) = r {
@@ -183,7 +208,24 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
Ok(())
}
- fn push_stack_frame(&mut self, mir: CachedMir<'a, 'tcx>, substs: &'tcx Substs<'tcx>,
+ fn call_nested(&mut self, mir: &mir::Mir<'tcx>) -> EvalResult