summaryrefslogtreecommitdiffstats
path: root/library/core/src/panicking.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/panicking.rs')
-rw-r--r--library/core/src/panicking.rs39
1 files changed, 26 insertions, 13 deletions
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index a704a00fa..48e90e6d7 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -1,8 +1,8 @@
-//! Panic support for libcore
+//! Panic support for core
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
-//! means that the functions inside of libcore are allowed to panic, but to be
-//! useful an upstream crate must define panicking for libcore to use. The current
+//! means that the functions inside of core are allowed to panic, but to be
+//! useful an upstream crate must define panicking for core to use. The current
//! interface for panicking is:
//!
//! ```
@@ -13,7 +13,7 @@
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
-//! The reason for this is that libcore is not allowed to allocate.
+//! The reason for this is that core is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
@@ -64,12 +64,17 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
unsafe { panic_impl(&pi) }
}
-/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.
-/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed.
+/// Like `panic_fmt`, but for non-unwinding panics.
+///
+/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute.
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[track_caller]
+// This attribute has the key side-effect that if the panic handler ignores `can_unwind`
+// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
+// which causes a "panic in a function that cannot unwind".
#[rustc_nounwind]
-pub fn panic_str_nounwind(msg: &'static str) -> ! {
+pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
if cfg!(feature = "panic_immediate_abort") {
super::intrinsics::abort()
}
@@ -82,8 +87,6 @@ pub fn panic_str_nounwind(msg: &'static str) -> ! {
}
// PanicInfo with the `can_unwind` flag set to false forces an abort.
- let pieces = [msg];
- let fmt = fmt::Arguments::new_v1(&pieces, &[]);
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
@@ -93,7 +96,7 @@ pub fn panic_str_nounwind(msg: &'static str) -> ! {
// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
// above.
-/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
+/// The underlying implementation of core's `panic!` macro when no formatting is used.
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
@@ -111,6 +114,15 @@ pub const fn panic(expr: &'static str) -> ! {
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}
+/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[rustc_nounwind]
+pub fn panic_nounwind(expr: &'static str) -> ! {
+ panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+}
+
#[inline]
#[track_caller]
#[rustc_diagnostic_item = "panic_str"]
@@ -153,10 +165,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
+#[cfg_attr(bootstrap, lang = "panic_no_unwind")] // needed by codegen for panic in nounwind function
+#[cfg_attr(not(bootstrap), lang = "panic_cannot_unwind")] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
-fn panic_no_unwind() -> ! {
- panic_str_nounwind("panic in a function that cannot unwind")
+fn panic_cannot_unwind() -> ! {
+ panic_nounwind("panic in a function that cannot unwind")
}
/// This function is used instead of panic_fmt in const eval.