Skip to content

Commit 0df6e33

Browse files
de-vri-esjakoschiko
authored andcommitted
Add assertion details to panic info.
The assertion details are added as a new enum field, allowing for future extensions with different information for other sources of panics. For example, `.unwrap()` could extend the enum to store a `&dyn Error` in the panic info. The panic handler in `std` passes the additional info unmodified to the panic hook.
1 parent 3d71e74 commit 0df6e33

File tree

7 files changed

+222
-28
lines changed

7 files changed

+222
-28
lines changed

library/core/src/macros/mod.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ macro_rules! assert_eq {
4141
// The reborrows below are intentional. Without them, the stack slot for the
4242
// borrow is initialized even before the values are compared, leading to a
4343
// noticeable slow down.
44-
$crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None);
44+
$crate::panicking::assert_failed(
45+
kind,
46+
$crate::stringify!($left),
47+
&*left_val,
48+
$crate::stringify!($right),
49+
&*right_val,
50+
$crate::option::Option::None,
51+
);
4552
}
4653
}
4754
}
@@ -54,7 +61,14 @@ macro_rules! assert_eq {
5461
// The reborrows below are intentional. Without them, the stack slot for the
5562
// borrow is initialized even before the values are compared, leading to a
5663
// noticeable slow down.
57-
$crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+)));
64+
$crate::panicking::assert_failed(
65+
kind,
66+
$crate::stringify!($left),
67+
&*left_val,
68+
$crate::stringify!($right),
69+
&*right_val,
70+
$crate::option::Option::Some($crate::format_args!($($arg)+)),
71+
);
5872
}
5973
}
6074
}
@@ -90,7 +104,14 @@ macro_rules! assert_ne {
90104
// The reborrows below are intentional. Without them, the stack slot for the
91105
// borrow is initialized even before the values are compared, leading to a
92106
// noticeable slow down.
93-
$crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None);
107+
$crate::panicking::assert_failed(
108+
kind,
109+
$crate::stringify!($left),
110+
&*left_val,
111+
$crate::stringify!($right),
112+
&*right_val,
113+
$crate::option::Option::None,
114+
);
94115
}
95116
}
96117
}
@@ -103,7 +124,14 @@ macro_rules! assert_ne {
103124
// The reborrows below are intentional. Without them, the stack slot for the
104125
// borrow is initialized even before the values are compared, leading to a
105126
// noticeable slow down.
106-
$crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+)));
127+
$crate::panicking::assert_failed(
128+
kind,
129+
$crate::stringify!($left),
130+
&*left_val,
131+
$crate::stringify!($right),
132+
&*right_val,
133+
$crate::option::Option::Some($crate::format_args!($($arg)+)),
134+
);
107135
}
108136
}
109137
}
@@ -145,6 +173,7 @@ pub macro assert_matches {
145173
$( $pattern )|+ $( if $guard )? => {}
146174
ref left_val => {
147175
$crate::panicking::assert_matches_failed(
176+
$crate::stringify!($left),
148177
left_val,
149178
$crate::stringify!($($pattern)|+ $(if $guard)?),
150179
$crate::option::Option::None
@@ -157,6 +186,7 @@ pub macro assert_matches {
157186
$( $pattern )|+ $( if $guard )? => {}
158187
ref left_val => {
159188
$crate::panicking::assert_matches_failed(
189+
$crate::stringify!($left),
160190
left_val,
161191
$crate::stringify!($($pattern)|+ $(if $guard)?),
162192
$crate::option::Option::Some($crate::format_args!($($arg)+))

library/core/src/panic.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@
55
mod location;
66
mod panic_info;
77
mod unwind_safe;
8+
#[unstable(
9+
feature = "panic_internals",
10+
reason = "internal details of the implementation of the `panic!` and related macros",
11+
issue = "none"
12+
)]
13+
#[doc(hidden)]
14+
pub mod assert_info;
15+
#[unstable(
16+
feature = "panic_internals",
17+
reason = "internal details of the implementation of the `panic!` and related macros",
18+
issue = "none"
19+
)]
20+
#[doc(hidden)]
21+
pub mod extra_info;
822

923
use crate::any::Any;
1024

@@ -36,7 +50,10 @@ pub macro panic_2015 {
3650
$crate::panicking::panic_display(&$arg)
3751
),
3852
($fmt:expr, $($arg:tt)+) => (
39-
$crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
53+
$crate::panicking::panic_fmt(
54+
$crate::const_format_args!($fmt, $($arg)+),
55+
$crate::option::Option::None,
56+
)
4057
),
4158
}
4259

@@ -54,7 +71,10 @@ pub macro panic_2021 {
5471
$crate::panicking::panic_display(&$arg)
5572
),
5673
($($t:tt)+) => (
57-
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
74+
$crate::panicking::panic_fmt(
75+
$crate::const_format_args!($($t)+),
76+
$crate::option::Option::None,
77+
)
5878
),
5979
}
6080

library/core/src/panic/assert_info.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use crate::fmt::Debug;
2+
3+
/// Information about a failed assertion.
4+
#[derive(Debug)]
5+
pub struct AssertInfo<'a> {
6+
/// The assertion that failed.
7+
pub assertion: Assertion<'a>,
8+
/// Optional additional message to include in the failure report.
9+
pub message: Option<crate::fmt::Arguments<'a>>,
10+
}
11+
12+
#[derive(Debug)]
13+
pub enum Assertion<'a> {
14+
/// The assertion is a boolean assertion.
15+
Bool(BoolAssertion),
16+
/// The assertion is a binary comparison assertion.
17+
Binary(BinaryAssertion<'a>),
18+
}
19+
20+
/// Information about a failed boolean assertion.
21+
#[derive(Debug)]
22+
pub struct BoolAssertion {
23+
/// The expression that was evaluated.
24+
pub expr: &'static str,
25+
}
26+
27+
/// Information about a failed binary comparison assertion.
28+
#[derive(Debug)]
29+
pub struct BinaryAssertion<'a> {
30+
/// The operator used to compare left and right.
31+
pub op: &'static str,
32+
/// The left expression as string.
33+
pub left_expr: &'static str,
34+
/// The right expression as string.
35+
pub right_expr: &'static str,
36+
/// The value of the left expression.
37+
pub left_val: &'a dyn Debug,
38+
/// The value of the right expression.
39+
pub right_val: &'a dyn Debug,
40+
}
41+
42+
impl<'a> From<BoolAssertion> for Assertion<'a> {
43+
fn from(other: BoolAssertion) -> Self {
44+
Self::Bool(other)
45+
}
46+
}
47+
48+
impl<'a> From<BinaryAssertion<'a>> for Assertion<'a> {
49+
fn from(other: BinaryAssertion<'a>) -> Self {
50+
Self::Binary(other)
51+
}
52+
}

library/core/src/panic/extra_info.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use crate::panic::assert_info::AssertInfo;
2+
3+
#[derive(Debug, Copy, Clone)]
4+
pub enum ExtraInfo<'a> {
5+
AssertInfo(&'a AssertInfo<'a>),
6+
}

library/core/src/panic/panic_info.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::any::Any;
22
use crate::fmt;
3+
use crate::panic::assert_info::AssertInfo;
4+
use crate::panic::extra_info::ExtraInfo;
35
use crate::panic::Location;
46

57
/// A struct providing information about a panic.
@@ -31,6 +33,7 @@ pub struct PanicInfo<'a> {
3133
payload: &'a (dyn Any + Send),
3234
message: Option<&'a fmt::Arguments<'a>>,
3335
location: &'a Location<'a>,
36+
extra_info: Option<ExtraInfo<'a>>,
3437
}
3538

3639
impl<'a> PanicInfo<'a> {
@@ -46,7 +49,7 @@ impl<'a> PanicInfo<'a> {
4649
location: &'a Location<'a>,
4750
) -> Self {
4851
struct NoPayload;
49-
PanicInfo { location, message, payload: &NoPayload }
52+
PanicInfo { location, message, payload: &NoPayload, extra_info: None }
5053
}
5154

5255
#[unstable(
@@ -124,6 +127,40 @@ impl<'a> PanicInfo<'a> {
124127
// deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
125128
Some(&self.location)
126129
}
130+
131+
#[unstable(
132+
feature = "panic_internals",
133+
reason = "internal details of the implementation of the `panic!` and related macros",
134+
issue = "none"
135+
)]
136+
#[doc(hidden)]
137+
#[inline]
138+
pub fn set_extra_info(&mut self, info: Option<ExtraInfo<'a>>) {
139+
self.extra_info = info;
140+
}
141+
142+
#[unstable(
143+
feature = "panic_internals",
144+
reason = "internal details of the implementation of the `panic!` and related macros",
145+
issue = "none"
146+
)]
147+
#[doc(hidden)]
148+
#[inline]
149+
pub fn extra_info(&self) -> Option<ExtraInfo<'_>> {
150+
self.extra_info
151+
}
152+
153+
/// Get the information about the assertion that caused the panic.
154+
///
155+
/// Returns `None` if the panic was not caused by an assertion.
156+
#[unstable(
157+
feature = "panic_internals",
158+
reason = "internal details of the implementation of the `panic!` and related macros",
159+
issue = "none"
160+
)]
161+
pub fn assert_info(&self) -> Option<&AssertInfo<'_>> {
162+
if let Some(ExtraInfo::AssertInfo(x)) = &self.extra_info { Some(x) } else { None }
163+
}
127164
}
128165

129166
#[stable(feature = "panic_hook_display", since = "1.26.0")]

0 commit comments

Comments
 (0)