Skip to content

Commit 55fbd97

Browse files
committed
add error source to panic info
1 parent a41fc00 commit 55fbd97

File tree

5 files changed

+72
-8
lines changed

5 files changed

+72
-8
lines changed

library/core/src/panic/panic_info.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::any::Any;
2+
use crate::error::Error;
23
use crate::fmt;
34
use crate::panic::Location;
45

@@ -30,6 +31,7 @@ use crate::panic::Location;
3031
pub struct PanicInfo<'a> {
3132
payload: &'a (dyn Any + Send),
3233
message: Option<&'a fmt::Arguments<'a>>,
34+
source: Option<&'a (dyn Error + 'static)>,
3335
location: &'a Location<'a>,
3436
can_unwind: bool,
3537
}
@@ -45,10 +47,11 @@ impl<'a> PanicInfo<'a> {
4547
pub fn internal_constructor(
4648
message: Option<&'a fmt::Arguments<'a>>,
4749
location: &'a Location<'a>,
50+
source: Option<&'a (dyn Error + 'static)>,
4851
can_unwind: bool,
4952
) -> Self {
5053
struct NoPayload;
51-
PanicInfo { location, message, payload: &NoPayload, can_unwind }
54+
PanicInfo { location, message, payload: &NoPayload, source, can_unwind }
5255
}
5356

5457
#[unstable(
@@ -62,6 +65,12 @@ impl<'a> PanicInfo<'a> {
6265
self.payload = info;
6366
}
6467

68+
#[unstable(feature = "error_in_panic", issue = "none")]
69+
/// FIXME
70+
pub fn source(&self) -> Option<&(dyn Error + 'static)> {
71+
self.source
72+
}
73+
6574
/// Returns the payload associated with the panic.
6675
///
6776
/// This will commonly, but not always, be a `&'static str` or [`String`].

library/core/src/panicking.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
issue = "none"
2727
)]
2828

29+
use crate::error::Error;
2930
use crate::fmt;
3031
use crate::panic::{Location, PanicInfo};
3132

@@ -50,6 +51,18 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C
5051
#[rustc_do_not_const_check] // hooked by const-eval
5152
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
5253
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
54+
panic_source(fmt, None)
55+
}
56+
57+
#[cold]
58+
// If panic_immediate_abort, inline the abort call,
59+
// otherwise avoid inlining because of it is cold path.
60+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
61+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
62+
#[track_caller]
63+
#[rustc_do_not_const_check] // hooked by const-eval
64+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
65+
pub const fn panic_source(fmt: fmt::Arguments<'_>, source: Option<& (dyn Error + 'static)>) -> ! {
5366
if cfg!(feature = "panic_immediate_abort") {
5467
super::intrinsics::abort()
5568
}
@@ -61,7 +74,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
6174
fn panic_impl(pi: &PanicInfo<'_>) -> !;
6275
}
6376

64-
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
77+
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), source, true);
6578

6679
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
6780
unsafe { panic_impl(&pi) }
@@ -90,7 +103,9 @@ pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
90103
}
91104

92105
// PanicInfo with the `can_unwind` flag set to false forces an abort.
93-
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
106+
let pieces = [msg];
107+
let fmt = fmt::Arguments::new_v1(&pieces, &[]);
108+
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), None, false);
94109

95110
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
96111
unsafe { panic_impl(&pi) }

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
#![feature(duration_constants)]
279279
#![feature(error_generic_member_access)]
280280
#![feature(error_in_core)]
281+
#![feature(error_in_panic)]
281282
#![feature(error_iter)]
282283
#![feature(exact_size_is_empty)]
283284
#![feature(exclusive_wrapper)]

library/std/src/panicking.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::panic::BacktraceStyle;
1313
use core::panic::{BoxMeUp, Location, PanicInfo};
1414

1515
use crate::any::Any;
16+
use crate::error::Error;
1617
use crate::fmt;
1718
use crate::intrinsics;
1819
use crate::mem::{self, ManuallyDrop};
@@ -258,7 +259,9 @@ fn default_hook(info: &PanicInfo<'_>) {
258259

259260
let write = |err: &mut dyn crate::io::Write| {
260261
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
261-
262+
if info.source().is_some() {
263+
writeln!(err, "fun is not allowed");
264+
}
262265
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
263266

264267
match backtrace {
@@ -574,15 +577,17 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
574577
}
575578

576579
let loc = info.location().unwrap(); // The current implementation always returns Some
580+
let source = info.source();
577581
let msg = info.message().unwrap(); // The current implementation always returns Some
578582
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
579583
if let Some(msg) = msg.as_str() {
580-
rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind());
584+
rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, source, info.can_unwind());
581585
} else {
582586
rust_panic_with_hook(
583587
&mut PanicPayload::new(msg),
584588
info.message(),
585589
loc,
590+
source,
586591
info.can_unwind(),
587592
);
588593
}
@@ -608,7 +613,7 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
608613

609614
let loc = Location::caller();
610615
return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
611-
rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true)
616+
rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, None, true)
612617
});
613618

614619
struct PanicPayload<A> {
@@ -653,6 +658,7 @@ fn rust_panic_with_hook(
653658
payload: &mut dyn BoxMeUp,
654659
message: Option<&fmt::Arguments<'_>>,
655660
location: &Location<'_>,
661+
source: Option<& (dyn Error + 'static)>,
656662
can_unwind: bool,
657663
) -> ! {
658664
let (must_abort, panics) = panic_count::increase();
@@ -670,13 +676,13 @@ fn rust_panic_with_hook(
670676
} else {
671677
// Unfortunately, this does not print a backtrace, because creating
672678
// a `Backtrace` will allocate, which we must to avoid here.
673-
let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind);
679+
let panicinfo = PanicInfo::internal_constructor(message, location, source, can_unwind);
674680
rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
675681
}
676682
crate::sys::abort_internal();
677683
}
678684

679-
let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
685+
let mut info = PanicInfo::internal_constructor(message, location, source, can_unwind);
680686
let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
681687
match *hook {
682688
// Some platforms (like wasm) know that printing to stderr won't ever actually
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// run-fail
2+
// check-run-results
3+
4+
#![allow(unused_imports)]
5+
#![feature(core_panic)]
6+
#![feature(error_in_core)]
7+
8+
extern crate core;
9+
10+
use core::panicking::panic_source;
11+
use core::error;
12+
13+
#[derive (Debug)]
14+
struct MyErr;
15+
16+
use std::fmt;
17+
impl fmt::Display for MyErr {
18+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
19+
write!(f, "my source error message")
20+
}
21+
}
22+
23+
impl error::Error for MyErr {
24+
25+
}
26+
27+
fn main() {
28+
std::env::set_var("RUST_BACKTRACE", "full");
29+
let source = MyErr;
30+
//FIXME make the function do the Some wrapping for us
31+
panic_source(format_args!("here's my panic error message"), Some(&source));
32+
33+
}

0 commit comments

Comments
 (0)