diff --git a/src/librustc_mir/interpret/error.rs b/src/librustc_mir/interpret/error.rs
index d487e23aa4ef..3b297ed5bd01 100644
--- a/src/librustc_mir/interpret/error.rs
+++ b/src/librustc_mir/interpret/error.rs
@@ -1,6 +1,5 @@
use std::error::Error;
use std::fmt;
-use std::path::{PathBuf, Path};
use rustc::mir;
use rustc::ty::{FnSig, Ty, layout};
@@ -11,41 +10,23 @@ use super::{
use rustc_const_math::ConstMathErr;
use syntax::codemap::Span;
+use backtrace::Backtrace;
#[derive(Debug)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx>,
- pub backtrace: Vec,
+ pub backtrace: Backtrace,
}
impl<'tcx> From> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx>) -> Self {
- let mut backtrace = Vec::new();
- use backtrace::{trace, resolve};
- trace(|frame| {
- resolve(frame.ip(), |symbol| {
- backtrace.push(Frame {
- function: symbol.name().map(|s| s.to_string()).unwrap_or(String::new()),
- file: symbol.filename().unwrap_or(Path::new("")).to_owned(),
- line: symbol.lineno().unwrap_or(0),
- });
- });
- true
- });
EvalError {
kind,
- backtrace,
+ backtrace: Backtrace::new(),
}
}
}
-#[derive(Debug)]
-pub struct Frame {
- pub function: String,
- pub file: PathBuf,
- pub line: u32,
-}
-
#[derive(Debug)]
pub enum EvalErrorKind<'tcx> {
/// This variant is used by machines to signal their own errors that do not
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 42c1bc656c3d..45d1a9905057 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1705,13 +1705,45 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
pub fn report(&self, e: &EvalError) {
let mut trace_text = "\n################################\nerror occurred in miri at\n".to_string();
- for frame in e.backtrace.iter().skip_while(|frame| frame.function.starts_with("backtrace::")) {
- // don't report initialization gibberish
- if frame.function == "miri::after_analysis" {
- break;
+ let mut skip_init = true;
+ 'frames: for (i, frame) in e.backtrace.frames().iter().enumerate() {
+ for symbol in frame.symbols() {
+ if let Some(name) = symbol.name() {
+ // unmangle the symbol via `to_string`
+ let name = name.to_string();
+ if name.starts_with("miri::after_analysis") {
+ // don't report initialization gibberish
+ break 'frames;
+ } else if name.starts_with("backtrace::capture::Backtrace::new")
+ // debug mode produces funky symbol names
+ || name.starts_with("backtrace::capture::{{impl}}::new") {
+ // don't report backtrace internals
+ skip_init = false;
+ continue 'frames;
+ }
+ }
+ }
+ if skip_init {
+ continue;
+ }
+ write!(trace_text, "{}\n", i).unwrap();
+ for symbol in frame.symbols() {
+ if let Some(name) = symbol.name() {
+ write!(trace_text, "# {}\n", name).unwrap();
+ } else {
+ write!(trace_text, "# \n").unwrap();
+ }
+ if let Some(file_path) = symbol.filename() {
+ write!(trace_text, "{}", file_path.display()).unwrap();
+ } else {
+ write!(trace_text, "").unwrap();
+ }
+ if let Some(line) = symbol.lineno() {
+ write!(trace_text, ":{}\n", line).unwrap();
+ } else {
+ write!(trace_text, "\n").unwrap();
+ }
}
- write!(trace_text, "# {}\n", frame.function).unwrap();
- write!(trace_text, "{}:{}\n", frame.file.display(), frame.line).unwrap();
}
trace!("{}", trace_text);
if let Some(frame) = self.stack().last() {