From 4de031b3da1c3dc8091a64daa46322ced3796c0f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 24 Dec 2019 00:11:40 +0100 Subject: [PATCH] Move error reporting to its own module --- src/diagnostics.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++ src/eval.rs | 60 -------------------------------------------- src/lib.rs | 2 ++ 3 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 src/diagnostics.rs diff --git a/src/diagnostics.rs b/src/diagnostics.rs new file mode 100644 index 000000000000..30be49ff770c --- /dev/null +++ b/src/diagnostics.rs @@ -0,0 +1,62 @@ +use rustc_mir::interpret::InterpErrorInfo; + +use crate::*; + +pub fn report_err<'tcx, 'mir>( + ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>, + mut e: InterpErrorInfo<'tcx>, +) -> Option { + // Special treatment for some error kinds + let msg = match e.kind { + InterpError::MachineStop(ref info) => { + let info = info.downcast_ref::().expect("invalid MachineStop payload"); + match info { + TerminationInfo::Exit(code) => return Some(*code), + TerminationInfo::PoppedTrackedPointerTag(item) => + format!("popped tracked tag for item {:?}", item), + TerminationInfo::Abort => format!("the evaluated program aborted execution"), + } + } + err_unsup!(NoMirFor(..)) => format!( + "{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`.", + e + ), + InterpError::InvalidProgram(_) => bug!("This error should be impossible in Miri: {}", e), + _ => e.to_string(), + }; + e.print_backtrace(); + if let Some(frame) = ecx.stack().last() { + let span = frame.current_source_info().unwrap().span; + + let msg = format!("Miri evaluation error: {}", msg); + let mut err = ecx.tcx.sess.struct_span_err(span, msg.as_str()); + let frames = ecx.generate_stacktrace(None); + err.span_label(span, msg); + // We iterate with indices because we need to look at the next frame (the caller). + for idx in 0..frames.len() { + let frame_info = &frames[idx]; + let call_site_is_local = frames + .get(idx + 1) + .map_or(false, |caller_info| caller_info.instance.def_id().is_local()); + if call_site_is_local { + err.span_note(frame_info.call_site, &frame_info.to_string()); + } else { + err.note(&frame_info.to_string()); + } + } + err.emit(); + } else { + ecx.tcx.sess.err(&msg); + } + + for (i, frame) in ecx.stack().iter().enumerate() { + trace!("-------------------"); + trace!("Frame {}", i); + trace!(" return: {:?}", frame.return_place.map(|p| *p)); + for (i, local) in frame.locals.iter().enumerate() { + trace!(" local {}: {:?}", i, local.value); + } + } + // Let the reported error determine the return code. + return None; +} diff --git a/src/eval.rs b/src/eval.rs index 9c15fedca3d0..e5dfbe32c12e 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -8,7 +8,6 @@ use rustc_hir::def_id::DefId; use rustc::ty::layout::{LayoutOf, Size}; use rustc::ty::{self, TyCtxt}; -use rustc_mir::interpret::InterpErrorInfo; use crate::*; @@ -209,62 +208,3 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) -> Err(e) => report_err(&ecx, e), } } - -fn report_err<'tcx, 'mir>( - ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>, - mut e: InterpErrorInfo<'tcx>, -) -> Option { - // Special treatment for some error kinds - let msg = match e.kind { - InterpError::MachineStop(ref info) => { - let info = info.downcast_ref::().expect("invalid MachineStop payload"); - match info { - TerminationInfo::Exit(code) => return Some(*code), - TerminationInfo::PoppedTrackedPointerTag(item) => - format!("popped tracked tag for item {:?}", item), - TerminationInfo::Abort => format!("the evaluated program aborted execution"), - } - } - err_unsup!(NoMirFor(..)) => format!( - "{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`.", - e - ), - InterpError::InvalidProgram(_) => bug!("This error should be impossible in Miri: {}", e), - _ => e.to_string(), - }; - e.print_backtrace(); - if let Some(frame) = ecx.stack().last() { - let span = frame.current_source_info().unwrap().span; - - let msg = format!("Miri evaluation error: {}", msg); - let mut err = ecx.tcx.sess.struct_span_err(span, msg.as_str()); - let frames = ecx.generate_stacktrace(None); - err.span_label(span, msg); - // We iterate with indices because we need to look at the next frame (the caller). - for idx in 0..frames.len() { - let frame_info = &frames[idx]; - let call_site_is_local = frames - .get(idx + 1) - .map_or(false, |caller_info| caller_info.instance.def_id().is_local()); - if call_site_is_local { - err.span_note(frame_info.call_site, &frame_info.to_string()); - } else { - err.note(&frame_info.to_string()); - } - } - err.emit(); - } else { - ecx.tcx.sess.err(&msg); - } - - for (i, frame) in ecx.stack().iter().enumerate() { - trace!("-------------------"); - trace!("Frame {}", i); - trace!(" return: {:?}", frame.return_place.map(|p| *p)); - for (i, local) in frame.locals.iter().enumerate() { - trace!(" local {}: {:?}", i, local.value); - } - } - // Let the reported error determine the return code. - return None; -} diff --git a/src/lib.rs b/src/lib.rs index 19a84db3e17e..b5925bb26c89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ extern crate rustc_mir; extern crate rustc_target; +mod diagnostics; mod eval; mod helpers; mod intptrcast; @@ -41,6 +42,7 @@ pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData}; pub use crate::shims::EvalContextExt as ShimsEvalContextExt; +pub use crate::diagnostics::report_err; pub use crate::eval::{create_ecx, eval_main, MiriConfig, TerminationInfo}; pub use crate::helpers::EvalContextExt as HelpersEvalContextExt; pub use crate::machine::{