diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index eed13a13fa911..9087163acdf31 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1423,6 +1423,7 @@ fn check_matcher_core<'tt>( | TokenTree::MetaVarExpr(..) => { if let TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } = token && !features.macro_guard_matcher() + && is_defined_in_current_crate(node_id) { feature_err( sess, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3451b2976bb73..e1e8d2fb68937 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -146,6 +146,7 @@ #![feature(lang_items)] #![feature(link_cfg)] #![feature(link_llvm_intrinsics)] +#![feature(macro_guard_matcher)] #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![feature(marker_trait_attr)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5fd7766633ce8..ddcf5653b7360 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -168,25 +168,25 @@ 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 )|+ $( $guard:guard )? $(,)?) => {{ match $left { - $( $pattern )|+ $( if $guard )? => {} + $( $pattern )|+ $( $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( left_val, - $crate::stringify!($($pattern)|+ $(if $guard)?), + $crate::stringify!($($pattern)|+ $($guard)?), $crate::option::Option::None ); } } }}, - ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {{ + ($left:expr, $(|)? $( $pattern:pat_param )|+ $( $guard:guard )?, $($arg:tt)+) => {{ match $left { - $( $pattern )|+ $( if $guard )? => {} + $( $pattern )|+ $( $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( left_val, - $crate::stringify!($($pattern)|+ $(if $guard)?), + $crate::stringify!($($pattern)|+ $($guard)?), $crate::option::Option::Some($crate::format_args!($($arg)+)) ); } @@ -424,10 +424,10 @@ pub macro debug_assert_matches($($arg:tt)*) { #[rustc_diagnostic_item = "matches_macro"] #[allow_internal_unstable(non_exhaustive_omitted_patterns_lint, stmt_expr_attributes)] macro_rules! matches { - ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { + ($expression:expr, $pattern:pat $($guard:guard)? $(,)?) => { #[allow(non_exhaustive_omitted_patterns)] match $expression { - $pattern $(if $guard)? => true, + $pattern $($guard)? => true, _ => false } }; diff --git a/library/coretests/tests/macros.rs b/library/coretests/tests/macros.rs index 9f73ebd253c3b..485e5a1b17866 100644 --- a/library/coretests/tests/macros.rs +++ b/library/coretests/tests/macros.rs @@ -46,6 +46,19 @@ fn matches_leading_pipe() { matches!(1, | 1 | 2 | 3); } +#[test] +fn matches_if_let_guard() { + assert!(matches!(Some(Some(1)), Some(x) if let Some(1) = x)); + assert!(matches!(Some(Some(Some(1))), Some(x) if let Some(y) = x && let Some(1) = y)); + assert!(!matches!(Some(Some(Some(1))), Some(x) if let Some(y) = x && let Some(2) = y)); + + assert_matches!(Some(Some(1)), Some(x) if let Some(1) = x); + assert_matches!(Some(Some(Some(1))), Some(x) if let Some(y) = x && let Some(1) = y); + + debug_assert_matches!(Some(Some(1)), Some(x) if let Some(1) = x); + debug_assert_matches!(Some(Some(Some(1))), Some(x) if let Some(y) = x && let Some(1) = y); +} + #[test] fn cfg_select_basic() { cfg_select! { diff --git a/tests/ui/macros/macro-guard-matcher.rs b/tests/ui/macros/macro-guard-matcher.rs index d66bae455c2c2..305b8e7f43085 100644 --- a/tests/ui/macros/macro-guard-matcher.rs +++ b/tests/ui/macros/macro-guard-matcher.rs @@ -16,10 +16,16 @@ fn main() { m!(let Some(x) = Some(1)); //~ERROR no rules expected keyword `let` macro_rules! m_m { - ($g:guard) => { m!($g); }; + (case1, $g:guard) => { + m!($g) + }; + (case2, if $e:expr) => { + m!(if $e) + }; } // Accepted since `m` recognizes that the sequence produced by the expansion of // metavar `$g` "begins" (i.e., is) a guard since it's of kind `guard`. - m_m!(if true); + m_m!(case1, if true); + m_m!(case2, if true); }