Skip to content

Commit

Permalink
move const_panic/assert macros into core::panic module (since they ar…
Browse files Browse the repository at this point in the history
…e just internal helpers)
  • Loading branch information
RalfJung committed Nov 4, 2024
1 parent 5605568 commit 5c39b29
Show file tree
Hide file tree
Showing 19 changed files with 299 additions and 319 deletions.
2 changes: 1 addition & 1 deletion library/core/src/char/methods.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! impl char {}

use super::*;
use crate::macros::const_panic;
use crate::panic::const_panic;
use crate::slice;
use crate::str::from_utf8_unchecked_mut;
use crate::unicode::printable::is_printable;
Expand Down
8 changes: 4 additions & 4 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl CStr {
#[rustc_allow_const_fn_unstable(const_eval_select)]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
const_eval_select!(
(bytes: &[u8]) -> &CStr:
@capture { bytes: &[u8] } -> &CStr:
if const {
// Saturating so that an empty slice panics in the assert with a good
// message, not here due to underflow.
Expand All @@ -429,7 +429,7 @@ impl CStr {

// SAFETY: See runtime cast comment below.
unsafe { &*(bytes as *const [u8] as *const CStr) }
} else #[inline] {
} else {
// Chance at catching some UB at runtime with debug builds.
debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);

Expand Down Expand Up @@ -735,7 +735,7 @@ impl AsRef<CStr> for CStr {
#[rustc_allow_const_fn_unstable(const_eval_select)]
const unsafe fn strlen(ptr: *const c_char) -> usize {
const_eval_select!(
(s: *const c_char = ptr) -> usize:
@capture { s: *const c_char = ptr } -> usize:
if const {
let mut len = 0;

Expand All @@ -745,7 +745,7 @@ const unsafe fn strlen(ptr: *const c_char) -> usize {
}

len
} else #[inline] {
} else {
extern "C" {
/// Provided by libc or compiler_builtins.
fn strlen(s: *const c_char) -> usize;
Expand Down
27 changes: 15 additions & 12 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2791,31 +2791,36 @@ where
/// A macro to make it easier to invoke const_eval_select. Use as follows:
/// ```rust,ignore (just a macro example)
/// const_eval_select!(
/// #[inline]
/// (arg1: i32 = some_expr, arg2: T = other_expr) -> U:
/// if const {
/// @capture { arg1: i32 = some_expr, arg2: T = other_expr } -> U:
/// if const #[attributes_for_const_arm] {
/// // Compile-time code goes here.
/// } else {
/// } else #[attributes_for_runtime_arm] {
/// // Run-time code goes here.
/// }
/// )
/// ```
/// The `@capture` block declares which surrounding variables / expressions can be
/// used inside the `if const`.
/// Note that the two arms of this `if` really each become their own function, which is why the
/// macro supports setting attributes for those functions. The runtime function is always
/// markes as `#[inline]`.
///
/// See [`const_eval_select()`] for the rules and requirements around that intrinsic.
pub(crate) macro const_eval_select {
(
@capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
$(#[$attr:meta])*
($($arg:ident : $ty:ty = $val:expr),* $(,)?) $( -> $ret:ty )?:
if const
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
) => {{
$(#[$attr])*
$(#[$runtime_attr])*
#[inline]
fn runtime($($arg: $ty),*) $( -> $ret )? {
$runtime
}

$(#[$attr])*
$(#[$compiletime_attr])*
const fn compiletime($($arg: $ty),*) $( -> $ret )? {
// Don't warn if one of the arguments is unused.
Expand All @@ -2829,16 +2834,14 @@ pub(crate) macro const_eval_select {
// We support leaving away the `val` expressions for *all* arguments
// (but not for *some* arguments, that's too tricky).
(
$(#[$attr:meta])*
($($arg:ident : $ty:ty),* $(,)?) -> $ret:ty:
@capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? :
if const
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
) => {
$crate::intrinsics::const_eval_select!(
$(#[$attr])*
($($arg : $ty = $arg),*) -> $ret:
@capture { $($arg : $ty = $arg),* } $(-> $ret)? :
if const
$(#[$compiletime_attr])* $compiletime
else
Expand Down Expand Up @@ -3794,7 +3797,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
}

const_eval_select!(
(ptr: *const (), align: usize):
@capture { ptr: *const (), align: usize}:
if const {
// Do nothing.
} else {
Expand Down
58 changes: 0 additions & 58 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,6 @@ 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),* $(,)?) => {{
// 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!(
#[inline]
#[track_caller]
($($arg: $ty),*) -> !:
if const {
$crate::panic!($const_msg)
} else {
$crate::panic!($runtime_msg)
}
)
}

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
Expand Down Expand Up @@ -241,19 +196,6 @@ 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
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
use crate::macros::const_assert;
use crate::mem;
use crate::num::FpCategory;
use crate::panic::const_assert;

/// Basic mathematical constants.
#[unstable(feature = "f128", issue = "116909")]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
use crate::macros::const_assert;
use crate::mem;
use crate::num::FpCategory;
use crate::panic::const_assert;

/// Basic mathematical constants.
#[unstable(feature = "f16", issue = "116909")]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
use crate::macros::const_assert;
use crate::mem;
use crate::num::FpCategory;
use crate::panic::const_assert;

/// The radix or base of the internal representation of `f32`.
/// Use [`f32::RADIX`] instead.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
use crate::macros::const_assert;
use crate::mem;
use crate::num::FpCategory;
use crate::panic::const_assert;

/// The radix or base of the internal representation of `f64`.
/// Use [`f64::RADIX`] instead.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#![stable(feature = "rust1", since = "1.0.0")]

use crate::macros::const_panic;
use crate::panic::const_panic;
use crate::str::FromStr;
use crate::ub_checks::assert_unsafe_precondition;
use crate::{ascii, intrinsics, mem};
Expand Down
56 changes: 56 additions & 0 deletions library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,59 @@ pub unsafe trait PanicPayload: crate::fmt::Display {
None
}
}

/// 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),* $(,)?) => {{
// 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!(
@capture { $($arg: $ty),* } -> !:
if const #[track_caller] {
$crate::panic!($const_msg)
} else #[track_caller] {
$crate::panic!($runtime_msg)
}
)
}

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::panic::const_panic!(
$const_msg,
$runtime_msg,
$($arg: $ty = $arg),*
)
},
}

/// 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::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
}
}}
}
62 changes: 29 additions & 33 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
)]

use crate::fmt;
use crate::intrinsics::const_eval_select;
use crate::panic::{Location, PanicInfo};

#[cfg(feature = "panic_immediate_abort")]
Expand Down Expand Up @@ -89,40 +90,35 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
#[rustc_allow_const_fn_unstable(const_eval_select)]
pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
#[inline] // this should always be inlined into `panic_nounwind_fmt`
#[track_caller]
fn runtime(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
if cfg!(feature = "panic_immediate_abort") {
super::intrinsics::abort()
const_eval_select!(
@capture { fmt: fmt::Arguments<'_>, force_no_backtrace: bool } -> !:
if const #[track_caller] {
// We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
panic_fmt(fmt)
} else #[track_caller] {
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<'_>) -> !;
}

// PanicInfo with the `can_unwind` flag set to false forces an abort.
let pi = PanicInfo::new(
&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) }
}

// 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::new(
&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) }
}

#[inline]
#[track_caller]
const fn comptime(fmt: fmt::Arguments<'_>, _force_no_backtrace: bool) -> ! {
// We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
panic_fmt(fmt);
}

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
Expand Down
Loading

0 comments on commit 5c39b29

Please sign in to comment.