about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2023-04-14 01:14:26 +0100
committerGary Guo <gary@garyguo.net>2023-11-25 23:58:51 +0000
commit4ccec4558fea4c649ef92874bb26f3e96ab8eb21 (patch)
treed3ef12ebcbc76c8042d4209ae317351bf221a6ed /library/core/src
parentf5dc2653fdd8b5d177b2ccbd84057954340a89fc (diff)
downloadrust-4ccec4558fea4c649ef92874bb26f3e96ab8eb21.tar.gz
rust-4ccec4558fea4c649ef92874bb26f3e96ab8eb21.zip
Add `debug_assert_nounwind`
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/panic.rs21
-rw-r--r--library/core/src/panicking.rs52
2 files changed, 54 insertions, 19 deletions
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index b7cd10b5b19..f5d18ca0b3f 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -139,6 +139,27 @@ pub macro unreachable_2021 {
     ),
 }
 
+#[doc(hidden)]
+#[unstable(feature = "core_panic", issue = "none")]
+#[allow_internal_unstable(core_panic, const_format_args)]
+#[rustc_macro_transparency = "semitransparent"]
+pub macro debug_assert_nounwind {
+    ($cond:expr $(,)?) => {
+        if $crate::cfg!(debug_assertions) {
+            if !$cond {
+                $crate::panicking::panic_nounwind($crate::concat!("assertion failed: ", $crate::stringify!($cond)));
+            }
+        }
+    },
+    ($cond:expr, $($arg:tt)+) => {
+        if $crate::cfg!(debug_assertions) {
+            if !$cond {
+                $crate::panicking::panic_nounwind_fmt($crate::const_format_args!($($arg)+), false);
+            }
+        }
+    },
+}
+
 /// An internal trait used by std to pass data from std to `panic_unwind` and
 /// other panic runtimes. Not intended to be stabilized any time soon, do not
 /// use.
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index fa6e5fe5d17..1c906b7d3b4 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -82,28 +82,41 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
 // 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_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
-        super::intrinsics::abort()
-    }
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
+    fn runtime(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
+        if cfg!(feature = "panic_immediate_abort") {
+            super::intrinsics::abort()
+        }
 
-    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
-    // that gets resolved to the `#[panic_handler]` function.
-    extern "Rust" {
-        #[lang = "panic_impl"]
-        fn panic_impl(pi: &PanicInfo<'_>) -> !;
+        // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
+        // that gets resolved to the `#[panic_handler]` function.
+        extern "Rust" {
+            #[lang = "panic_impl"]
+            fn panic_impl(pi: &PanicInfo<'_>) -> !;
+        }
+
+        // PanicInfo with the `can_unwind` flag set to false forces an abort.
+        let pi = PanicInfo::internal_constructor(
+            Some(&fmt),
+            Location::caller(),
+            /* can_unwind */ false,
+            force_no_backtrace,
+        );
+
+        // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
+        unsafe { panic_impl(&pi) }
     }
 
-    // PanicInfo with the `can_unwind` flag set to false forces an abort.
-    let pi = PanicInfo::internal_constructor(
-        Some(&fmt),
-        Location::caller(),
-        /* can_unwind */ false,
-        force_no_backtrace,
-    );
+    #[inline]
+    const fn comptime(fmt: fmt::Arguments<'_>, _force_no_backtrace: bool) -> ! {
+        panic_fmt(fmt);
+    }
 
-    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
-    unsafe { panic_impl(&pi) }
+    // SAFETY: const panic does not care about unwinding
+    unsafe {
+        super::intrinsics::const_eval_select((fmt, force_no_backtrace), comptime, runtime);
+    }
 }
 
 // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
@@ -132,7 +145,8 @@ pub const fn panic(expr: &'static str) -> ! {
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
 #[rustc_nounwind]
-pub fn panic_nounwind(expr: &'static str) -> ! {
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_nounwind(expr: &'static str) -> ! {
     panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false);
 }