Skip to content

Commit 1372f5b

Browse files
committed
Add debug_assert_nounwind
1 parent a41fc00 commit 1372f5b

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

library/core/src/panic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,27 @@ pub macro unreachable_2021 {
9090
),
9191
}
9292

93+
#[doc(hidden)]
94+
#[unstable(feature = "core_panic", issue = "none")]
95+
#[allow_internal_unstable(core_panic, const_format_args)]
96+
#[rustc_macro_transparency = "semitransparent"]
97+
pub macro debug_assert_nounwind {
98+
($cond:expr $(,)?) => {
99+
if $crate::cfg!(debug_assertions) {
100+
if !$cond {
101+
$crate::panicking::panic_nounwind($crate::concat!("assertion failed: ", $crate::stringify!($cond)));
102+
}
103+
}
104+
},
105+
($cond:expr, $($arg:tt)+) => {
106+
if $crate::cfg!(debug_assertions) {
107+
if !$cond {
108+
$crate::panicking::panic_nounwind_fmt($crate::const_format_args!($($arg)+));
109+
}
110+
}
111+
},
112+
}
113+
93114
/// An internal trait used by std to pass data from std to `panic_unwind` and
94115
/// other panic runtimes. Not intended to be stabilized any time soon, do not
95116
/// use.

library/core/src/panicking.rs

+28-14
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,36 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
7777
// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
7878
// which causes a "panic in a function that cannot unwind".
7979
#[rustc_nounwind]
80-
pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
81-
if cfg!(feature = "panic_immediate_abort") {
82-
super::intrinsics::abort()
83-
}
80+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
81+
pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
82+
fn runtime(fmt: fmt::Arguments<'_>) -> ! {
83+
if cfg!(feature = "panic_immediate_abort") {
84+
super::intrinsics::abort()
85+
}
8486

85-
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
86-
// that gets resolved to the `#[panic_handler]` function.
87-
extern "Rust" {
88-
#[lang = "panic_impl"]
89-
fn panic_impl(pi: &PanicInfo<'_>) -> !;
87+
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
88+
// that gets resolved to the `#[panic_handler]` function.
89+
extern "Rust" {
90+
#[lang = "panic_impl"]
91+
fn panic_impl(pi: &PanicInfo<'_>) -> !;
92+
}
93+
94+
// PanicInfo with the `can_unwind` flag set to false forces an abort.
95+
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
96+
97+
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
98+
unsafe { panic_impl(&pi) }
9099
}
91100

92-
// PanicInfo with the `can_unwind` flag set to false forces an abort.
93-
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
101+
#[inline]
102+
const fn comptime(fmt: fmt::Arguments<'_>) -> ! {
103+
panic_fmt(fmt);
104+
}
94105

95-
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
96-
unsafe { panic_impl(&pi) }
106+
// SAFETY: const panic does not care about unwinding
107+
unsafe {
108+
super::intrinsics::const_eval_select((fmt,), comptime, runtime);
109+
}
97110
}
98111

99112
// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
@@ -122,7 +135,8 @@ pub const fn panic(expr: &'static str) -> ! {
122135
#[cfg_attr(feature = "panic_immediate_abort", inline)]
123136
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
124137
#[rustc_nounwind]
125-
pub fn panic_nounwind(expr: &'static str) -> ! {
138+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
139+
pub const fn panic_nounwind(expr: &'static str) -> ! {
126140
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
127141
}
128142

0 commit comments

Comments
 (0)