diff --git a/Cargo.toml b/Cargo.toml index 48e6075e..1d249b7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ supports-color = { version = "2.0.0", optional = true } supports-unicode = { version = "2.0.0", optional = true } backtrace = { version = "0.3.61", optional = true } terminal_size = { version = "0.1.17", optional = true } +backtrace-ext = { version = "0.2.1", optional = true } [dev-dependencies] semver = "1.0.4" @@ -41,19 +42,8 @@ lazy_static = "1.4" [features] default = [] -fancy-no-backtrace = [ - "owo-colors", - "is-terminal", - "textwrap", - "terminal_size", - "supports-hyperlinks", - "supports-color", - "supports-unicode", -] -fancy = [ - "fancy-no-backtrace", - "backtrace", -] +fancy-no-backtrace = ["owo-colors", "is-terminal", "textwrap", "terminal_size", "supports-hyperlinks", "supports-color", "supports-unicode"] +fancy = ["fancy-no-backtrace", "backtrace", "backtrace-ext"] [workspace] members = ["miette-derive"] diff --git a/src/panic.rs b/src/panic.rs index baf4e0c9..ad98cacb 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,6 +1,3 @@ -#![cfg(feature = "fancy")] -use std::fmt::Write; - use backtrace::Backtrace; use thiserror::Error; @@ -29,20 +26,22 @@ pub fn set_panic_hook() { } #[derive(Debug, Error, Diagnostic)] -#[error("{0}{}", self.maybe_collect_backtrace())] +#[error("{0}{}", Panic::backtrace())] #[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))] struct Panic(String); impl Panic { - fn maybe_collect_backtrace(&self) -> String { + fn backtrace() -> String { + use std::fmt::Write; if let Ok(var) = std::env::var("RUST_BACKTRACE") { if !var.is_empty() && var != "0" { - // This is all taken from human-panic: https://github.com/rust-cli/human-panic/blob/master/src/report.rs#L55-L107 const HEX_WIDTH: usize = std::mem::size_of::() + 2; - //Padding for next lines after frame's address + // Padding for next lines after frame's address const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; let mut backtrace = String::new(); - for (idx, frame) in Backtrace::new().frames().iter().skip(26).enumerate() { + let trace = Backtrace::new(); + let frames = backtrace_ext::short_frames_strict(&trace).enumerate(); + for (idx, (frame, sub_frames)) in frames { let ip = frame.ip(); let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH); @@ -52,10 +51,10 @@ impl Panic { continue; } - for (idx, symbol) in symbols.iter().enumerate() { - //Print symbols from this address, - //if there are several addresses - //we need to put it on next line + for (idx, symbol) in symbols[sub_frames].iter().enumerate() { + // Print symbols from this address, + // if there are several addresses + // we need to put it on next line if idx != 0 { let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING); } @@ -66,7 +65,7 @@ impl Panic { let _ = write!(backtrace, " - "); } - //See if there is debug information with file name and line + // See if there is debug information with file name and line if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { let _ = write!( backtrace,