From e3a4baed0166f60ffea835532bc934050250b164 Mon Sep 17 00:00:00 2001 From: Asuna Date: Thu, 19 Feb 2026 02:02:40 +0000 Subject: [PATCH] Support if-let-guard in `matches!` and `assert_matches!` --- library/core/src/macros/mod.rs | 31 +++++++++++++++++++++++++++++++ library/coretests/tests/macros.rs | 10 ++++++++++ 2 files changed, 41 insertions(+) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index d900b4a21b36d..00b5ac6978b5d 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -192,6 +192,30 @@ pub macro assert_matches { } } }, + ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if let $($let_guards: tt)+ )? $(,)?) => { + match $left { + $( $pattern )|+ $( if let $($let_guards)+ )? => {} + ref left_val => { + $crate::panicking::assert_matches_failed( + left_val, + $crate::stringify!($($pattern)|+ $(if let $($let_guards)+)?), + $crate::option::Option::None + ); + } + } + }, + ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if let $($let_guards: tt)+ )?, $($arg:tt)+) => { + match $left { + $( $pattern )|+ $( if let $($let_guards)+ )? => {} + ref left_val => { + $crate::panicking::assert_matches_failed( + left_val, + $crate::stringify!($($pattern)|+ $(if let $($let_guards)+)?), + $crate::option::Option::Some($crate::format_args!($($arg)+)) + ); + } + } + }, } /// Selects code at compile-time based on `cfg` predicates. @@ -435,6 +459,13 @@ macro_rules! matches { _ => false } }; + ($expression:expr, $pattern:pat $(if let $($let_guards:tt)+)? $(,)?) => { + #[allow(non_exhaustive_omitted_patterns)] + match $expression { + $pattern $(if let $($let_guards)+)? => true, + _ => false + } + }; } /// Unwraps a result or propagates its error. diff --git a/library/coretests/tests/macros.rs b/library/coretests/tests/macros.rs index 50b5eb63e43a7..7fd3fc367ceda 100644 --- a/library/coretests/tests/macros.rs +++ b/library/coretests/tests/macros.rs @@ -44,6 +44,16 @@ fn matches_leading_pipe() { matches!(1, | 1 | 2 | 3); } +#[test] +fn matches_if_let_guard() { + use std::assert_matches; + + assert!( + matches!(Some(Some(2_i32)), Some(inner) if let Some(value) = inner && value.pow(2) == 4) + ); + assert_matches!(Some(Some(2_i32)), Some(inner) if let Some(value) = inner && value.pow(2) == 4); +} + #[test] fn cfg_select_basic() { cfg_select! {