diff --git a/benches/helpers/miri_helper.rs b/benches/helpers/miri_helper.rs index 2bf78b0a71cc..0fbb46246aea 100644 --- a/benches/helpers/miri_helper.rs +++ b/benches/helpers/miri_helper.rs @@ -5,8 +5,7 @@ extern crate rustc_driver; extern crate test; use self::miri::eval_main; -use self::rustc::session::Session; -use self::rustc_driver::{driver, CompilerCalls, Compilation}; +use self::rustc_driver::{driver, Compilation}; use std::cell::RefCell; use std::rc::Rc; use test::Bencher; @@ -36,37 +35,26 @@ pub fn run(filename: &str, bencher: &mut Bencher) { "--sysroot".to_string(), find_sysroot(), ]; - let compiler_calls = &mut MiriCompilerCalls(Rc::new(RefCell::new(bencher))); - rustc_driver::run_compiler(args, compiler_calls, None, None); -} + let bencher = RefCell::new(bencher); -impl<'a> CompilerCalls<'a> for MiriCompilerCalls<'a> { - fn build_controller( - &mut self, - _: &Session, - _: &getopts::Matches, - ) -> driver::CompileController<'a> { - let mut control: driver::CompileController<'a> = driver::CompileController::basic(); + let mut control = driver::CompileController::basic(); - let bencher = self.0.clone(); + control.after_analysis.stop = Compilation::Stop; + control.after_analysis.callback = Box::new(move |state| { + state.session.abort_if_errors(); - control.after_analysis.stop = Compilation::Stop; - control.after_analysis.callback = Box::new(move |state| { - state.session.abort_if_errors(); + let tcx = state.tcx.unwrap(); + let (entry_node_id, _, _) = state.session.entry_fn.borrow().expect( + "no main or start function found", + ); + let entry_def_id = tcx.hir.local_def_id(entry_node_id); - let tcx = state.tcx.unwrap(); - let (entry_node_id, _, _) = state.session.entry_fn.borrow().expect( - "no main or start function found", - ); - let entry_def_id = tcx.hir.local_def_id(entry_node_id); - - bencher.borrow_mut().iter(|| { - eval_main(tcx, entry_def_id, None); - }); - - state.session.abort_if_errors(); + bencher.borrow_mut().iter(|| { + eval_main(tcx, entry_def_id, None); }); - control - } + state.session.abort_if_errors(); + }); + + rustc_driver::run_compiler(args, Box::new(control), None, None); } diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs index ecc5287c7277..3e2cd032a80e 100644 --- a/rustc_tests/src/main.rs +++ b/rustc_tests/src/main.rs @@ -24,7 +24,7 @@ use rustc::ty::TyCtxt; use syntax::ast; struct MiriCompilerCalls { - default: RustcDefaultCalls, + default: Box, /// whether we are building for the host host_target: bool, } @@ -63,11 +63,12 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { ) -> Compilation { self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile) } - fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> { - let mut control = self.default.build_controller(sess, matches); + fn build_controller(self: Box, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> { + let this = *self; + let mut control = this.default.build_controller(sess, matches); control.after_hir_lowering.callback = Box::new(after_hir_lowering); control.after_analysis.callback = Box::new(after_analysis); - if !self.host_target { + if !this.host_target { // only fully compile targets on the host control.after_analysis.stop = Compilation::Stop; } @@ -182,10 +183,10 @@ fn main() { let buf = BufWriter::default(); let output = buf.clone(); let result = std::panic::catch_unwind(|| { - rustc_driver::run_compiler(&args, &mut MiriCompilerCalls { - default: RustcDefaultCalls, + rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls { + default: Box::new(RustcDefaultCalls), host_target, - }, None, Some(Box::new(buf))); + }), None, Some(Box::new(buf))); }); match result { diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 8d80135cde30..35e83d49125e 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -23,7 +23,7 @@ use syntax::ast; use std::path::PathBuf; struct MiriCompilerCalls { - default: RustcDefaultCalls, + default: Box, /// Whether to begin interpretation at the start_fn lang item or not /// /// If false, the interpretation begins at the `main` function @@ -78,13 +78,14 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { self.default.late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile) } fn build_controller( - &mut self, + self: Box, sess: &Session, matches: &getopts::Matches, ) -> CompileController<'a> { - let mut control = self.default.build_controller(sess, matches); + let this = *self; + let mut control = this.default.build_controller(sess, matches); control.after_hir_lowering.callback = Box::new(after_hir_lowering); - let start_fn = self.start_fn; + let start_fn = this.start_fn; control.after_analysis.callback = Box::new(move |state| after_analysis(state, start_fn)); if sess.target.target != sess.host { // only fully compile targets on the host. linking will fail for cross-compilation. @@ -234,8 +235,8 @@ fn main() { // Make sure we always have all the MIR (e.g. for auxilary builds in unit tests). args.push("-Zalways-encode-mir".to_owned()); - rustc_driver::run_compiler(&args, &mut MiriCompilerCalls { - default: RustcDefaultCalls, + rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls { + default: Box::new(RustcDefaultCalls), start_fn, - }, None, None); + }), None, None); } diff --git a/src/lib.rs b/src/lib.rs index e8bbe164611d..d2ee39dd995a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ use rustc::ty::layout::{TyLayout, LayoutOf, Size}; use rustc::ty::subst::Subst; use rustc::hir::def_id::DefId; use rustc::mir; +use rustc::middle::const_val; use syntax::ast::Mutability; use syntax::codemap::Span; @@ -253,9 +254,26 @@ pub fn eval_main<'a, 'tcx: 'a>( //tcx.sess.err("the evaluated program leaked memory"); } } - Err(mut e) => { - ecx.tcx.sess.err(&e.to_string()); - ecx.report(&mut e, true, None); + Err(e) => { + if let Some(frame) = ecx.stack().last() { + let block = &frame.mir.basic_blocks()[frame.block]; + let span = if frame.stmt < block.statements.len() { + block.statements[frame.stmt].source_info.span + } else { + block.terminator().source_info.span + }; + + let mut err = const_val::struct_error(ecx.tcx.tcx.at(span), "constant evaluation error"); + let (frames, span) = ecx.generate_stacktrace(None); + err.span_label(span, e.to_string()); + for const_val::FrameInfo { span, location, .. } in frames { + err.span_note(span, &format!("inside call to `{}`", location)); + } + err.emit(); + } else { + ecx.tcx.sess.err(&e.to_string()); + } + for (i, frame) in ecx.stack().iter().enumerate() { trace!("-------------------"); trace!("Frame {}", i);