diff --git a/src/error.rs b/src/error.rs index fde3db15968..a465ad62b9d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,7 @@ use syntax::codemap::Span; #[derive(Clone, Debug)] pub enum EvalError<'tcx> { FunctionPointerTyMismatch(&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>), + NoMirFor(String), DanglingPointerDeref, InvalidMemoryAccess, InvalidFunctionPointer, @@ -82,6 +83,8 @@ impl<'tcx> Error for EvalError<'tcx> { "array index out of bounds", EvalError::Math(..) => "mathematical operation failed", + EvalError::NoMirFor(..) => + "mir not found", EvalError::InvalidChar(..) => "tried to interpret an invalid 32-bit value as a char", EvalError::OutOfMemory{..} => @@ -113,6 +116,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "memory access of {}..{} outside bounds of allocation {} which has size {}", ptr.offset, ptr.offset + size, ptr.alloc_id, allocation_size) }, + EvalError::NoMirFor(ref func) => write!(f, "no mir for `{}`", func), EvalError::FunctionPointerTyMismatch(expected, got) => write!(f, "tried to call a function of type {:?} through a function pointer of type {:?}", expected, got), EvalError::ArrayIndexOutOfBounds(span, len, index) => diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index c9b51a6213a..14f522d3370 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -267,22 +267,25 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty.is_sized(self.tcx, &self.tcx.empty_parameter_environment(), DUMMY_SP) } - pub fn load_mir(&self, def_id: DefId) -> CachedMir<'a, 'tcx> { + pub fn load_mir(&self, def_id: DefId) -> EvalResult<'tcx, CachedMir<'a, 'tcx>> { + trace!("load mir {:?}", def_id); if def_id.is_local() { - CachedMir::Ref(self.mir_map.map.get(&def_id).unwrap()) + Ok(CachedMir::Ref(self.mir_map.map.get(&def_id).unwrap())) } else { let mut mir_cache = self.mir_cache.borrow_mut(); if let Some(mir) = mir_cache.get(&def_id) { - return CachedMir::Owned(mir.clone()); + return Ok(CachedMir::Owned(mir.clone())); } let cs = &self.tcx.sess.cstore; - let mir = cs.maybe_get_item_mir(self.tcx, def_id).unwrap_or_else(|| { - panic!("no mir for `{}`", self.tcx.item_path_str(def_id)); - }); - let cached = Rc::new(mir); - mir_cache.insert(def_id, cached.clone()); - CachedMir::Owned(cached) + match cs.maybe_get_item_mir(self.tcx, def_id) { + Some(mir) => { + let cached = Rc::new(mir); + mir_cache.insert(def_id, cached.clone()); + Ok(CachedMir::Owned(cached)) + }, + None => Err(EvalError::NoMirFor(self.tcx.item_path_str(def_id))), + } } } diff --git a/src/interpreter/step.rs b/src/interpreter/step.rs index f87f5e43a96..beecece0cb9 100644 --- a/src/interpreter/step.rs +++ b/src/interpreter/step.rs @@ -125,8 +125,8 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { if self.ecx.statics.contains_key(&cid) { return; } - let mir = self.ecx.load_mir(def_id); self.try(|this| { + let mir = this.ecx.load_mir(def_id)?; let ptr = this.ecx.alloc_ret_ptr(mir.return_ty, substs)?; this.ecx.statics.insert(cid.clone(), ptr); let cleanup = if immutable && !mir.return_ty.type_contents(this.ecx.tcx).interior_unsafe() { diff --git a/src/interpreter/terminator/mod.rs b/src/interpreter/terminator/mod.rs index 2189a15cfaf..cd024d4c007 100644 --- a/src/interpreter/terminator/mod.rs +++ b/src/interpreter/terminator/mod.rs @@ -184,7 +184,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (def_id, substs) }; - let mir = self.load_mir(resolved_def_id); + let mir = self.load_mir(resolved_def_id)?; let (return_ptr, return_to_block) = match destination { Some((ptr, block)) => (Some(ptr), StackPopCleanup::Goto(block)), None => (None, StackPopCleanup::None),