Add temporary scope to assert_matches

Addresses https://github.com/rust-lang/rust/issues/154406 in part.
assert_eq will be done in a separate PR.
This commit is contained in:
Lukas Bergdoll
2026-04-17 13:02:23 +02:00
parent 1b8f2e46e1
commit e0ef87f880
2 changed files with 27 additions and 4 deletions
+4 -4
View File
@@ -168,7 +168,7 @@ macro_rules! assert_ne {
#[allow_internal_unstable(panic_internals)]
#[rustc_macro_transparency = "semiopaque"]
pub macro assert_matches {
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {{
match $left {
$( $pattern )|+ $( if $guard )? => {}
ref left_val => {
@@ -179,8 +179,8 @@ macro_rules! assert_ne {
);
}
}
},
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {
}},
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {{
match $left {
$( $pattern )|+ $( if $guard )? => {}
ref left_val => {
@@ -191,7 +191,7 @@ macro_rules! assert_ne {
);
}
}
},
}},
}
/// Selects code at compile-time based on `cfg` predicates.
+23
View File
@@ -1,5 +1,7 @@
#![allow(unused_must_use)]
use std::{assert_matches, debug_assert_matches};
#[allow(dead_code)]
trait Trait {
fn blah(&self);
@@ -219,3 +221,24 @@ fn _matches_does_not_trigger_non_exhaustive_omitted_patterns_lint(o: core::sync:
// Ordering is a #[non_exhaustive] enum from a separate crate
let _m = matches!(o, core::sync::atomic::Ordering::Relaxed);
}
struct MutRefWithDrop<'a>(&'a mut u32);
// MutRefWithDrop needs to have a non-trivial drop to encounter potential lifetime issues if the
// macros don't introduce a temporary scope.
impl Drop for MutRefWithDrop<'_> {
fn drop(&mut self) {
*self.0 = u32::MAX;
}
}
#[test]
fn temporary_scope_introduction() {
// Fails to compile if the macros don't introduce a temporary scope, since `&mut val` would
// create a second mutable borrow while `MutRefWithDrop` still holds a unique ref.
let mut val = 0;
(assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val));
(debug_assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val));
}