Skip to content

Commit f61ab58

Browse files
Rollup merge of #81022 - seanchen1991:feat/frames-iter, r=KodrAus
Add Frames Iterator for Backtrace Second attempt at adding the ability to iterate over the frames of a Backtrace by exposing the frames method.
2 parents a188791 + 050643a commit f61ab58

File tree

2 files changed

+92
-38
lines changed

2 files changed

+92
-38
lines changed

library/std/src/backtrace.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,14 @@ fn _assert_send_sync() {
147147
_assert::<Backtrace>();
148148
}
149149

150-
struct BacktraceFrame {
150+
/// A single frame of a backtrace.
151+
#[unstable(feature = "backtrace_frames", issue = "79676")]
152+
pub struct BacktraceFrame {
151153
frame: RawFrame,
152154
symbols: Vec<BacktraceSymbol>,
153155
}
154156

157+
#[derive(Debug)]
155158
enum RawFrame {
156159
Actual(backtrace_rs::Frame),
157160
#[cfg(test)]
@@ -196,6 +199,14 @@ impl fmt::Debug for Backtrace {
196199
}
197200
}
198201

202+
impl fmt::Debug for BacktraceFrame {
203+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
204+
let mut dbg = fmt.debug_list();
205+
dbg.entries(&self.symbols);
206+
dbg.finish()
207+
}
208+
}
209+
199210
impl fmt::Debug for BacktraceSymbol {
200211
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
201212
// FIXME: improve formatting: https://github.com/rust-lang/rust/issues/65280
@@ -353,6 +364,14 @@ impl Backtrace {
353364
}
354365
}
355366

367+
impl<'a> Backtrace {
368+
/// Returns an iterator over the backtrace frames.
369+
#[unstable(feature = "backtrace_frames", issue = "79676")]
370+
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
371+
if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
372+
}
373+
}
374+
356375
impl fmt::Display for Backtrace {
357376
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
358377
let capture = match &self.inner {

library/std/src/backtrace/tests.rs

+72-37
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,52 @@
11
use super::*;
22

3+
fn generate_fake_frames() -> Vec<BacktraceFrame> {
4+
vec![
5+
BacktraceFrame {
6+
frame: RawFrame::Fake,
7+
symbols: vec![BacktraceSymbol {
8+
name: Some(b"std::backtrace::Backtrace::create".to_vec()),
9+
filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
10+
lineno: Some(100),
11+
colno: None,
12+
}],
13+
},
14+
BacktraceFrame {
15+
frame: RawFrame::Fake,
16+
symbols: vec![BacktraceSymbol {
17+
name: Some(b"__rust_maybe_catch_panic".to_vec()),
18+
filename: None,
19+
lineno: None,
20+
colno: None,
21+
}],
22+
},
23+
BacktraceFrame {
24+
frame: RawFrame::Fake,
25+
symbols: vec![
26+
BacktraceSymbol {
27+
name: Some(b"std::rt::lang_start_internal".to_vec()),
28+
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
29+
lineno: Some(300),
30+
colno: Some(5),
31+
},
32+
BacktraceSymbol {
33+
name: Some(b"std::rt::lang_start".to_vec()),
34+
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
35+
lineno: Some(400),
36+
colno: None,
37+
},
38+
],
39+
},
40+
]
41+
}
42+
343
#[test]
444
fn test_debug() {
545
let backtrace = Backtrace {
646
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
747
actual_start: 1,
848
resolved: true,
9-
frames: vec![
10-
BacktraceFrame {
11-
frame: RawFrame::Fake,
12-
symbols: vec![BacktraceSymbol {
13-
name: Some(b"std::backtrace::Backtrace::create".to_vec()),
14-
filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
15-
lineno: Some(100),
16-
colno: None,
17-
}],
18-
},
19-
BacktraceFrame {
20-
frame: RawFrame::Fake,
21-
symbols: vec![BacktraceSymbol {
22-
name: Some(b"__rust_maybe_catch_panic".to_vec()),
23-
filename: None,
24-
lineno: None,
25-
colno: None,
26-
}],
27-
},
28-
BacktraceFrame {
29-
frame: RawFrame::Fake,
30-
symbols: vec![
31-
BacktraceSymbol {
32-
name: Some(b"std::rt::lang_start_internal".to_vec()),
33-
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
34-
lineno: Some(300),
35-
colno: Some(5),
36-
},
37-
BacktraceSymbol {
38-
name: Some(b"std::rt::lang_start".to_vec()),
39-
filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
40-
lineno: Some(400),
41-
colno: None,
42-
},
43-
],
44-
},
45-
],
49+
frames: generate_fake_frames(),
4650
})),
4751
};
4852

@@ -58,3 +62,34 @@ fn test_debug() {
5862
// Format the backtrace a second time, just to make sure lazily resolved state is stable
5963
assert_eq!(format!("{:#?}", backtrace), expected);
6064
}
65+
66+
#[test]
67+
fn test_frames() {
68+
let backtrace = Backtrace {
69+
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
70+
actual_start: 1,
71+
resolved: true,
72+
frames: generate_fake_frames(),
73+
})),
74+
};
75+
76+
let frames = backtrace.frames();
77+
78+
#[rustfmt::skip]
79+
let expected = vec![
80+
"[
81+
{ fn: \"std::backtrace::Backtrace::create\", file: \"rust/backtrace.rs\", line: 100 },
82+
]",
83+
"[
84+
{ fn: \"__rust_maybe_catch_panic\" },
85+
]",
86+
"[
87+
{ fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },
88+
{ fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },
89+
]"
90+
];
91+
92+
let mut iter = frames.iter().zip(expected.iter());
93+
94+
assert!(iter.all(|(f, e)| format!("{:#?}", f) == *e));
95+
}

0 commit comments

Comments
 (0)