Add assert_matches!(expr, pat).
This commit is contained in:
parent
7f32f62aa5
commit
eb18746bc6
|
@ -110,6 +110,58 @@ macro_rules! assert_ne {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asserts that an expression matches a pattern.
|
||||||
|
///
|
||||||
|
/// On panic, this macro will print the value of the expression with its
|
||||||
|
/// debug representation.
|
||||||
|
///
|
||||||
|
/// Like [`assert!`], this macro has a second form, where a custom
|
||||||
|
/// panic message can be provided.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let a = 1u32.checked_add(2);
|
||||||
|
/// let b = 1u32.checked_sub(2);
|
||||||
|
/// assert_matches!(a, Some(_));
|
||||||
|
/// assert_matches!(b, None);
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
#[unstable(feature = "assert_matches", issue = "none")]
|
||||||
|
#[allow_internal_unstable(core_panic)]
|
||||||
|
macro_rules! assert_matches {
|
||||||
|
($left:expr, $right:pat $(,)?) => ({
|
||||||
|
match &$left {
|
||||||
|
left_val => {
|
||||||
|
if let $right = left_val {
|
||||||
|
// OK
|
||||||
|
} else {
|
||||||
|
$crate::panicking::assert_matches_failed(
|
||||||
|
&*left_val,
|
||||||
|
$crate::stringify!($right),
|
||||||
|
$crate::option::Option::None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($left:expr, $right:expr, $($arg:tt)+) => ({
|
||||||
|
match &$left {
|
||||||
|
left_val => {
|
||||||
|
if let $right = left_val {
|
||||||
|
// OK
|
||||||
|
} else {
|
||||||
|
$crate::panicking::assert_matches_failed(
|
||||||
|
&*left_val,
|
||||||
|
$crate::stringify!($right),
|
||||||
|
$crate::option::Option::Some($crate::format_args!($($arg)+))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts that a boolean expression is `true` at runtime.
|
/// Asserts that a boolean expression is `true` at runtime.
|
||||||
///
|
///
|
||||||
/// This will invoke the [`panic!`] macro if the provided expression cannot be
|
/// This will invoke the [`panic!`] macro if the provided expression cannot be
|
||||||
|
|
|
@ -97,6 +97,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||||
pub enum AssertKind {
|
pub enum AssertKind {
|
||||||
Eq,
|
Eq,
|
||||||
Ne,
|
Ne,
|
||||||
|
Match,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal function for `assert_eq!` and `assert_ne!` macros
|
/// Internal function for `assert_eq!` and `assert_ne!` macros
|
||||||
|
@ -113,32 +114,54 @@ where
|
||||||
T: fmt::Debug + ?Sized,
|
T: fmt::Debug + ?Sized,
|
||||||
U: fmt::Debug + ?Sized,
|
U: fmt::Debug + ?Sized,
|
||||||
{
|
{
|
||||||
#[track_caller]
|
assert_failed_inner(kind, &left, &right, args)
|
||||||
fn inner(
|
}
|
||||||
kind: AssertKind,
|
|
||||||
left: &dyn fmt::Debug,
|
|
||||||
right: &dyn fmt::Debug,
|
|
||||||
args: Option<fmt::Arguments<'_>>,
|
|
||||||
) -> ! {
|
|
||||||
let op = match kind {
|
|
||||||
AssertKind::Eq => "==",
|
|
||||||
AssertKind::Ne => "!=",
|
|
||||||
};
|
|
||||||
|
|
||||||
match args {
|
/// Internal function for `assert_match!`
|
||||||
Some(args) => panic!(
|
#[cold]
|
||||||
r#"assertion failed: `(left {} right)`
|
#[track_caller]
|
||||||
left: `{:?}`,
|
#[doc(hidden)]
|
||||||
right: `{:?}: {}`"#,
|
pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
|
||||||
op, left, right, args
|
left: &T,
|
||||||
),
|
right: &str,
|
||||||
None => panic!(
|
args: Option<fmt::Arguments<'_>>,
|
||||||
r#"assertion failed: `(left {} right)`
|
) -> ! {
|
||||||
left: `{:?}`,
|
// Use the Display implementation to display the pattern.
|
||||||
right: `{:?}`"#,
|
struct Pattern<'a>(&'a str);
|
||||||
op, left, right,
|
impl fmt::Debug for Pattern<'_> {
|
||||||
),
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(self.0, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inner(kind, &left, &right, args)
|
assert_failed_inner(AssertKind::Match, &left, &Pattern(right), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Non-generic version of the above functions, to avoid code bloat.
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_failed_inner(
|
||||||
|
kind: AssertKind,
|
||||||
|
left: &dyn fmt::Debug,
|
||||||
|
right: &dyn fmt::Debug,
|
||||||
|
args: Option<fmt::Arguments<'_>>,
|
||||||
|
) -> ! {
|
||||||
|
let op = match kind {
|
||||||
|
AssertKind::Eq => "==",
|
||||||
|
AssertKind::Ne => "!=",
|
||||||
|
AssertKind::Match => "matches",
|
||||||
|
};
|
||||||
|
|
||||||
|
match args {
|
||||||
|
Some(args) => panic!(
|
||||||
|
r#"assertion failed: `(left {} right)`
|
||||||
|
left: `{:?}`,
|
||||||
|
right: `{:?}: {}`"#,
|
||||||
|
op, left, right, args
|
||||||
|
),
|
||||||
|
None => panic!(
|
||||||
|
r#"assertion failed: `(left {} right)`
|
||||||
|
left: `{:?}`,
|
||||||
|
right: `{:?}`"#,
|
||||||
|
op, left, right,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,7 @@
|
||||||
#![feature(arbitrary_self_types)]
|
#![feature(arbitrary_self_types)]
|
||||||
#![feature(array_error_internals)]
|
#![feature(array_error_internals)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
|
#![feature(assert_matches)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(atomic_mut_ptr)]
|
#![feature(atomic_mut_ptr)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
@ -550,8 +551,8 @@ pub use std_detect::detect;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[allow(deprecated, deprecated_in_future)]
|
#[allow(deprecated, deprecated_in_future)]
|
||||||
pub use core::{
|
pub use core::{
|
||||||
assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, r#try, todo,
|
assert_eq, assert_matches, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches,
|
||||||
unimplemented, unreachable, write, writeln,
|
r#try, todo, unimplemented, unreachable, write, writeln,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Re-export built-in macros defined through libcore.
|
// Re-export built-in macros defined through libcore.
|
||||||
|
|
Loading…
Reference in New Issue