diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index e5f828c4c0b34..63aec14f48100 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -36,3 +36,5 @@ compiler-builtins-c = ["compiler_builtins/c"] compiler-builtins-no-asm = ["compiler_builtins/no-asm"] compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"] compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"] +# Make panics and failed asserts immediately abort without formatting any message +panic_immediate_abort = [] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index a548de814c53d..2499f1053d860 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -377,13 +377,20 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { panic!("allocation failed"); } + #[inline] fn rt_error(layout: Layout) -> ! { unsafe { __rust_alloc_error_handler(layout.size(), layout.align()); } } - unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) } + #[cfg(not(feature = "panic_immediate_abort"))] + unsafe { + core::intrinsics::const_eval_select((layout,), ct_error, rt_error) + } + + #[cfg(feature = "panic_immediate_abort")] + ct_error(layout) } // For alloc test `std::alloc::handle_alloc_error` can be used directly. diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 625b67a79ad09..bd66ad612196d 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -530,7 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. #[cfg(not(no_global_oom_handling))] -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] fn capacity_overflow() -> ! { panic!("capacity overflow"); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3b12c1bee0b76..f372aeba766ec 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1447,7 +1447,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap_remove(&mut self, index: usize) -> T { #[cold] - #[inline(never)] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] fn assert_failed(index: usize, len: usize) -> ! { panic!("swap_remove index (is {index}) should be < len (is {len})"); } @@ -1488,7 +1488,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, index: usize, element: T) { #[cold] - #[inline(never)] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] fn assert_failed(index: usize, len: usize) -> ! { panic!("insertion index (is {index}) should be <= len (is {len})"); } @@ -1549,8 +1549,7 @@ impl Vec { #[track_caller] pub fn remove(&mut self, index: usize) -> T { #[cold] - #[inline(never)] - #[track_caller] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] fn assert_failed(index: usize, len: usize) -> ! { panic!("removal index (is {index}) should be < len (is {len})"); } @@ -2148,7 +2147,7 @@ impl Vec { A: Clone, { #[cold] - #[inline(never)] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] fn assert_failed(at: usize, len: usize) -> ! { panic!("`at` split index (is {at}) should be <= len (is {len})"); } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index f3d8b54d4e949..0978b3c92805e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -755,7 +755,7 @@ impl Display for BorrowMutError { } // This ensures the panicking code is outlined from `borrow_mut` for `RefCell`. -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] fn panic_already_borrowed(err: BorrowMutError) -> ! { @@ -763,7 +763,7 @@ fn panic_already_borrowed(err: BorrowMutError) -> ! { } // This ensures the panicking code is outlined from `borrow` for `RefCell`. -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] fn panic_already_mutably_borrowed(err: BorrowError) -> ! { diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 7e7b6b4dbe9b1..6a53909a8f128 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -267,6 +267,7 @@ impl DerefMut for AssertUnwindSafe { impl R> FnOnce<()> for AssertUnwindSafe { type Output = R; + #[inline] extern "rust-call" fn call_once(self, _args: ()) -> R { (self.0)() } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 6aba9b6450941..27178328be5c1 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -81,6 +81,7 @@ use iter::{MatchesInternal, SplitNInternal}; #[cold] #[track_caller] #[rustc_allow_const_fn_unstable(const_eval_select)] +#[cfg(not(feature = "panic_immediate_abort"))] const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { // SAFETY: panics for both branches unsafe { @@ -92,6 +93,11 @@ const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { } } +#[cfg(feature = "panic_immediate_abort")] +const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { + slice_error_fail_ct(s, begin, end) +} + #[track_caller] const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! { panic!("failed to slice string"); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 3b57f864e20da..2eb7608c7ae63 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -72,7 +72,7 @@ llvm-libunwind = ["unwind/llvm-libunwind"] system-llvm-libunwind = ["unwind/system-llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message -panic_immediate_abort = ["core/panic_immediate_abort"] +panic_immediate_abort = ["core/panic_immediate_abort", "alloc/panic_immediate_abort"] # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index d7a2baa1ff570..55f4917a93705 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -295,12 +295,53 @@ fn default_hook(info: &PanicInfo<'_>) { #[cfg(not(test))] #[doc(hidden)] +#[cfg(feature = "panic_immediate_abort")] +#[unstable(feature = "update_panic_count", issue = "none")] +pub mod panic_count { + /// A reason for forcing an immediate abort on panic. + #[derive(Debug)] + pub enum MustAbort { + AlwaysAbort, + PanicInHook, + } + + #[inline] + pub fn increase(run_panic_hook: bool) -> Option { + None + } + + #[inline] + pub fn finished_panic_hook() {} + + #[inline] + pub fn decrease() {} + + #[inline] + pub fn set_always_abort() {} + + // Disregards ALWAYS_ABORT_FLAG + #[inline] + #[must_use] + pub fn get_count() -> usize { + 0 + } + + #[must_use] + #[inline] + pub fn count_is_zero() -> bool { + true + } +} + +#[cfg(not(test))] +#[doc(hidden)] +#[cfg(not(feature = "panic_immediate_abort"))] #[unstable(feature = "update_panic_count", issue = "none")] pub mod panic_count { use crate::cell::Cell; use crate::sync::atomic::{AtomicUsize, Ordering}; - pub const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1); + const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1); /// A reason for forcing an immediate abort on panic. #[derive(Debug)] @@ -421,6 +462,13 @@ pub mod panic_count { pub use realstd::rt::panic_count; /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. +#[cfg(feature = "panic_immediate_abort")] +pub unsafe fn r#try R>(f: F) -> Result> { + Ok(f()) +} + +/// Invoke a closure, capturing the cause of an unwinding panic if one occurs. +#[cfg(not(feature = "panic_immediate_abort"))] pub unsafe fn r#try R>(f: F) -> Result> { union Data { f: ManuallyDrop, @@ -755,6 +803,7 @@ fn rust_panic_with_hook( /// This is the entry point for `resume_unwind`. /// It just forwards the payload to the panic runtime. +#[cfg_attr(feature = "panic_immediate_abort", inline)] pub fn rust_panic_without_hook(payload: Box) -> ! { panic_count::increase(false); @@ -777,7 +826,16 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { /// yer breakpoints. #[inline(never)] #[cfg_attr(not(test), rustc_std_internal_symbol)] +#[cfg(not(feature = "panic_immediate_abort"))] fn rust_panic(msg: &mut dyn PanicPayload) -> ! { let code = unsafe { __rust_start_panic(msg) }; rtabort!("failed to initiate panic, error {code}") } + +#[cfg_attr(not(test), rustc_std_internal_symbol)] +#[cfg(feature = "panic_immediate_abort")] +fn rust_panic(_: &mut dyn PanicPayload) -> ! { + unsafe { + crate::intrinsics::abort(); + } +}