about summary refs log tree commit diff
path: root/library/core/src/macros/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/macros/mod.rs')
-rw-r--r--library/core/src/macros/mod.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 771c2d31b60..9a91ff82acd 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -12,6 +12,54 @@ macro_rules! panic {
     };
 }
 
+/// Helper macro for panicking in a `const fn`.
+/// Invoke as:
+/// ```rust,ignore (just an example)
+/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
+/// ```
+/// where the first message will be printed in const-eval,
+/// and the second message will be printed at runtime.
+// All uses of this macro are FIXME(const-hack).
+#[unstable(feature = "panic_internals", issue = "none")]
+#[doc(hidden)]
+pub macro const_panic {
+    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
+        #[inline]
+        #[track_caller]
+        fn runtime($($arg: $ty),*) -> ! {
+            $crate::panic!($runtime_msg);
+        }
+
+        #[inline]
+        #[track_caller]
+        const fn compiletime($(_: $ty),*) -> ! {
+            $crate::panic!($const_msg);
+        }
+
+        // Wrap call to `const_eval_select` in a function so that we can
+        // add the `rustc_allow_const_fn_unstable`. This is okay to do
+        // because both variants will panic, just with different messages.
+        #[rustc_allow_const_fn_unstable(const_eval_select)]
+        #[inline(always)]
+        #[track_caller]
+        #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))]
+        const fn do_panic($($arg: $ty),*) -> ! {
+            $crate::intrinsics::const_eval_select(($($arg),* ,), compiletime, runtime)
+        }
+
+        do_panic($($val),*)
+    }},
+    // We support leaving away the `val` expressions for *all* arguments
+    // (but not for *some* arguments, that's too tricky).
+    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
+        $crate::macros::const_panic!(
+            $const_msg,
+            $runtime_msg,
+            $($arg: $ty = $arg),*
+        )
+    },
+}
+
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// Assertions are always checked in both debug and release builds, and cannot
@@ -196,6 +244,19 @@ pub macro assert_matches {
     },
 }
 
+/// A version of `assert` that prints a non-formatting message in const contexts.
+///
+/// See [`const_panic!`].
+#[unstable(feature = "panic_internals", issue = "none")]
+#[doc(hidden)]
+pub macro const_assert {
+    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
+        if !$crate::intrinsics::likely($condition) {
+            $crate::macros::const_panic!($const_msg, $runtime_msg, $($arg)*)
+        }
+    }}
+}
+
 /// A macro for defining `#[cfg]` match-like statements.
 ///
 /// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of