Add Frames iterator for Backtrace
This commit is contained in:
parent
a62a76047e
commit
050643a960
@ -147,11 +147,14 @@ fn _assert<T: Send + Sync>() {}
|
||||
_assert::<Backtrace>();
|
||||
}
|
||||
|
||||
struct BacktraceFrame {
|
||||
/// A single frame of a backtrace.
|
||||
#[unstable(feature = "backtrace_frames", issue = "79676")]
|
||||
pub struct BacktraceFrame {
|
||||
frame: RawFrame,
|
||||
symbols: Vec<BacktraceSymbol>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum RawFrame {
|
||||
Actual(backtrace_rs::Frame),
|
||||
#[cfg(test)]
|
||||
@ -196,6 +199,14 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BacktraceFrame {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut dbg = fmt.debug_list();
|
||||
dbg.entries(&self.symbols);
|
||||
dbg.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BacktraceSymbol {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME: improve formatting: https://github.com/rust-lang/rust/issues/65280
|
||||
@ -353,6 +364,14 @@ pub fn status(&self) -> BacktraceStatus {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Backtrace {
|
||||
/// Returns an iterator over the backtrace frames.
|
||||
#[unstable(feature = "backtrace_frames", issue = "79676")]
|
||||
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
|
||||
if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Backtrace {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let capture = match &self.inner {
|
||||
|
@ -1,48 +1,52 @@
|
||||
use super::*;
|
||||
|
||||
fn generate_fake_frames() -> Vec<BacktraceFrame> {
|
||||
vec![
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![BacktraceSymbol {
|
||||
name: Some(b"std::backtrace::Backtrace::create".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
|
||||
lineno: Some(100),
|
||||
colno: None,
|
||||
}],
|
||||
},
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![BacktraceSymbol {
|
||||
name: Some(b"__rust_maybe_catch_panic".to_vec()),
|
||||
filename: None,
|
||||
lineno: None,
|
||||
colno: None,
|
||||
}],
|
||||
},
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![
|
||||
BacktraceSymbol {
|
||||
name: Some(b"std::rt::lang_start_internal".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
|
||||
lineno: Some(300),
|
||||
colno: Some(5),
|
||||
},
|
||||
BacktraceSymbol {
|
||||
name: Some(b"std::rt::lang_start".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
|
||||
lineno: Some(400),
|
||||
colno: None,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let backtrace = Backtrace {
|
||||
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
|
||||
actual_start: 1,
|
||||
resolved: true,
|
||||
frames: vec![
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![BacktraceSymbol {
|
||||
name: Some(b"std::backtrace::Backtrace::create".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
|
||||
lineno: Some(100),
|
||||
colno: None,
|
||||
}],
|
||||
},
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![BacktraceSymbol {
|
||||
name: Some(b"__rust_maybe_catch_panic".to_vec()),
|
||||
filename: None,
|
||||
lineno: None,
|
||||
colno: None,
|
||||
}],
|
||||
},
|
||||
BacktraceFrame {
|
||||
frame: RawFrame::Fake,
|
||||
symbols: vec![
|
||||
BacktraceSymbol {
|
||||
name: Some(b"std::rt::lang_start_internal".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
|
||||
lineno: Some(300),
|
||||
colno: Some(5),
|
||||
},
|
||||
BacktraceSymbol {
|
||||
name: Some(b"std::rt::lang_start".to_vec()),
|
||||
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
|
||||
lineno: Some(400),
|
||||
colno: None,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
frames: generate_fake_frames(),
|
||||
})),
|
||||
};
|
||||
|
||||
@ -58,3 +62,34 @@ fn test_debug() {
|
||||
// Format the backtrace a second time, just to make sure lazily resolved state is stable
|
||||
assert_eq!(format!("{:#?}", backtrace), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_frames() {
|
||||
let backtrace = Backtrace {
|
||||
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
|
||||
actual_start: 1,
|
||||
resolved: true,
|
||||
frames: generate_fake_frames(),
|
||||
})),
|
||||
};
|
||||
|
||||
let frames = backtrace.frames();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let expected = vec![
|
||||
"[
|
||||
{ fn: \"std::backtrace::Backtrace::create\", file: \"rust/backtrace.rs\", line: 100 },
|
||||
]",
|
||||
"[
|
||||
{ fn: \"__rust_maybe_catch_panic\" },
|
||||
]",
|
||||
"[
|
||||
{ fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },
|
||||
{ fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },
|
||||
]"
|
||||
];
|
||||
|
||||
let mut iter = frames.iter().zip(expected.iter());
|
||||
|
||||
assert!(iter.all(|(f, e)| format!("{:#?}", f) == *e));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user