Improve assert_eq! and assert_ne!

It should improve compile times and reduce instruction cache use by moving the
panic formatting to a monomorphised function
This commit is contained in:
Benoît du Garreau 2020-11-16 15:40:33 +01:00 committed by Benoît du Garreau
parent 5fa22fe6f8
commit bbad2b2182
3 changed files with 103 additions and 15 deletions

View file

@ -173,6 +173,13 @@ mod macros;
#[macro_use] #[macro_use]
mod internal_macros; mod internal_macros;
#[doc(hidden)]
#[unstable(
feature = "macros_internals",
reason = "macros implementation detail",
issue = "none"
)]
pub use macros::internals as macros_internals;
#[path = "num/shells/int_macros.rs"] #[path = "num/shells/int_macros.rs"]
#[macro_use] #[macro_use]

View file

@ -0,0 +1,85 @@
use crate::{fmt, panic};
#[cold]
#[doc(hidden)]
#[unstable(feature = "macros_internals", reason = "macros implementation detail", issue = "none")]
#[track_caller]
pub fn assert_eq_failed<T, U>(left: &T, right: &U) -> !
where
T: fmt::Debug + ?Sized,
U: fmt::Debug + ?Sized,
{
#[track_caller]
fn inner(left: &dyn fmt::Debug, right: &dyn fmt::Debug) -> ! {
panic!(
r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`"#,
left, right
)
}
inner(&left, &right)
}
#[cold]
#[doc(hidden)]
#[unstable(feature = "macros_internals", reason = "macros implementation detail", issue = "none")]
#[track_caller]
pub fn assert_eq_failed_args<T, U>(left: &T, right: &U, args: fmt::Arguments<'_>) -> !
where
T: fmt::Debug + ?Sized,
U: fmt::Debug + ?Sized,
{
#[track_caller]
fn inner(left: &dyn fmt::Debug, right: &dyn fmt::Debug, args: fmt::Arguments<'_>) -> ! {
panic!(
r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}: {}`"#,
left, right, args
)
}
inner(&left, &right, args)
}
#[cold]
#[doc(hidden)]
#[unstable(feature = "macros_internals", reason = "macros implementation detail", issue = "none")]
#[track_caller]
pub fn assert_ne_failed<T, U>(left: &T, right: &U) -> !
where
T: fmt::Debug + ?Sized,
U: fmt::Debug + ?Sized,
{
#[track_caller]
fn inner(left: &dyn fmt::Debug, right: &dyn fmt::Debug) -> ! {
panic!(
r#"assertion failed: `(left != right)`
left: `{:?}`,
right: `{:?}`"#,
left, right
)
}
inner(&left, &right)
}
#[cold]
#[doc(hidden)]
#[unstable(feature = "macros_internals", reason = "macros implementation detail", issue = "none")]
#[track_caller]
pub fn assert_ne_failed_args<T, U>(left: &T, right: &U, args: fmt::Arguments<'_>) -> !
where
T: fmt::Debug + ?Sized,
U: fmt::Debug + ?Sized,
{
#[track_caller]
fn inner(left: &dyn fmt::Debug, right: &dyn fmt::Debug, args: fmt::Arguments<'_>) -> ! {
panic!(
r#"assertion failed: `(left != right)`
left: `{:?}`,
right: `{:?}: {}`"#,
left, right, args
)
}
inner(&left, &right, args)
}

View file

@ -1,3 +1,7 @@
#[unstable(feature = "macros_internals", reason = "macros implementation detail", issue = "none")]
#[doc(hidden)]
pub mod internals;
#[cfg(bootstrap)] #[cfg(bootstrap)]
#[doc(include = "panic.md")] #[doc(include = "panic.md")]
#[macro_export] #[macro_export]
@ -53,6 +57,7 @@ macro_rules! panic {
/// ``` /// ```
#[macro_export] #[macro_export]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(macros_internals)]
macro_rules! assert_eq { macro_rules! assert_eq {
($left:expr, $right:expr $(,)?) => ({ ($left:expr, $right:expr $(,)?) => ({
match (&$left, &$right) { match (&$left, &$right) {
@ -61,24 +66,19 @@ macro_rules! assert_eq {
// The reborrows below are intentional. Without them, the stack slot for the // The reborrows below are intentional. Without them, the stack slot for the
// borrow is initialized even before the values are compared, leading to a // borrow is initialized even before the values are compared, leading to a
// noticeable slow down. // noticeable slow down.
$crate::panic!(r#"assertion failed: `(left == right)` $crate::macros_internals::assert_eq_failed(&*left_val, &*right_val);
left: `{:?}`,
right: `{:?}`"#, &*left_val, &*right_val)
} }
} }
} }
}); });
($left:expr, $right:expr, $($arg:tt)+) => ({ ($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) { match (&$left, &$right) {
(left_val, right_val) => { (left_val, right_val) => {
if !(*left_val == *right_val) { if !(*left_val == *right_val) {
// The reborrows below are intentional. Without them, the stack slot for the // The reborrows below are intentional. Without them, the stack slot for the
// borrow is initialized even before the values are compared, leading to a // borrow is initialized even before the values are compared, leading to a
// noticeable slow down. // noticeable slow down.
$crate::panic!(r#"assertion failed: `(left == right)` $crate::macros_internals::assert_eq_failed_args(&*left_val, &*right_val, $crate::format_args!($($arg)+));
left: `{:?}`,
right: `{:?}`: {}"#, &*left_val, &*right_val,
$crate::format_args!($($arg)+))
} }
} }
} }
@ -104,6 +104,7 @@ macro_rules! assert_eq {
/// ``` /// ```
#[macro_export] #[macro_export]
#[stable(feature = "assert_ne", since = "1.13.0")] #[stable(feature = "assert_ne", since = "1.13.0")]
#[allow_internal_unstable(macros_internals)]
macro_rules! assert_ne { macro_rules! assert_ne {
($left:expr, $right:expr $(,)?) => ({ ($left:expr, $right:expr $(,)?) => ({
match (&$left, &$right) { match (&$left, &$right) {
@ -112,9 +113,7 @@ macro_rules! assert_ne {
// The reborrows below are intentional. Without them, the stack slot for the // The reborrows below are intentional. Without them, the stack slot for the
// borrow is initialized even before the values are compared, leading to a // borrow is initialized even before the values are compared, leading to a
// noticeable slow down. // noticeable slow down.
$crate::panic!(r#"assertion failed: `(left != right)` $crate::macros_internals::assert_eq_failed(&*left_val, &*right_val);
left: `{:?}`,
right: `{:?}`"#, &*left_val, &*right_val)
} }
} }
} }
@ -126,10 +125,7 @@ macro_rules! assert_ne {
// The reborrows below are intentional. Without them, the stack slot for the // The reborrows below are intentional. Without them, the stack slot for the
// borrow is initialized even before the values are compared, leading to a // borrow is initialized even before the values are compared, leading to a
// noticeable slow down. // noticeable slow down.
$crate::panic!(r#"assertion failed: `(left != right)` $crate::macros_internals::assert_ne_failed_args(&*left_val, &*right_val, $crate::format_args!($($arg)+));
left: `{:?}`,
right: `{:?}`: {}"#, &*left_val, &*right_val,
$crate::format_args!($($arg)+))
} }
} }
} }