https://gcc.gnu.org/g:780ebba8a9152598e0fde0528c2fc63d9f474fcd

commit 780ebba8a9152598e0fde0528c2fc63d9f474fcd
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Tue Apr 8 14:41:16 2025 +0200

    expansion: Only add fragments if the matcher succeeded
    
    gcc/rust/ChangeLog:
    
            * expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do 
not
            insert fragments and substack fragments if the matcher failed.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/macros/mbe/macro-issue3708.rs: New test.

Diff:
---
 gcc/rust/expand/rust-macro-expand.cc               | 15 ++--
 .../rust/compile/macros/mbe/macro-issue3708.rs     | 80 ++++++++++++++++++++++
 2 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index 78297570791b..c22db1c8aeb6 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -621,9 +621,10 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> 
&parser,
                // matched fragment get the offset in the token stream
                size_t offs_end = source.get_offs ();
 
-               sub_stack.insert_metavar (
-                 MatchedFragment (fragment->get_ident ().as_string (),
-                                  offs_begin, offs_end));
+               if (valid_current_match)
+                 sub_stack.insert_metavar (
+                   MatchedFragment (fragment->get_ident ().as_string (),
+                                    offs_begin, offs_end));
              }
              break;
 
@@ -650,15 +651,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> 
&parser,
        }
       auto old_stack = sub_stack.pop ();
 
-      // nest metavars into repetitions
-      for (auto &ent : old_stack)
-       sub_stack.append_fragment (ent.first, std::move (ent.second));
-
       // If we've encountered an error once, stop trying to match more
       // repetitions
       if (!valid_current_match)
        break;
 
+      // nest metavars into repetitions
+      for (auto &ent : old_stack)
+       sub_stack.append_fragment (ent.first, std::move (ent.second));
+
       match_amount++;
 
       // Break early if we notice there's too many expressions already
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs 
b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
new file mode 100644
index 000000000000..e5b38bb0da7e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
@@ -0,0 +1,80 @@
+// { dg-additional-options "-frust-name-resolution-2.0 
-frust-compile-until=lowering" }
+
+macro_rules! impl_fn_for_zst {
+    ($(
+        $( #[$attr: meta] )*
+        struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
+            |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
+            $body: block;
+    )+) => {
+        $(
+            $( #[$attr] )*
+            struct $Name;
+
+            impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
+                #[inline]
+                extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, 
)*)) -> $ReturnTy {
+                    $body
+                }
+            }
+
+            impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
+                #[inline]
+                extern "rust-call" fn call_mut(
+                    &mut self,
+                    ($( $arg, )*): ($( $ArgTy, )*)
+                ) -> $ReturnTy {
+                    Fn::call(&*self, ($( $arg, )*))
+                }
+            }
+
+            impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
+                type Output = $ReturnTy;
+
+                #[inline]
+                extern "rust-call" fn call_once(self, ($( $arg, )*): ($( 
$ArgTy, )*)) -> $ReturnTy {
+                    Fn::call(&self, ($( $arg, )*))
+                }
+            }
+        )+
+    }
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "fn"]
+pub trait Fn<Args>: FnMut<Args> {
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_mut"]
+#[must_use = "closures are lazy and do nothing unless called"]
+pub trait FnMut<Args>: FnOnce<Args> {
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+    /// The returned type after the call operator is used.
+    #[lang = "fn_once_output"]
+    #[stable(feature = "fn_once_output", since = "1.12.0")]
+    type Output;
+
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+impl_fn_for_zst! {
+    #[derive(Copy)]
+    struct LinesAnyMap impl<'a> Fn = |line: &'a str| -> () {
+    };
+}

Reply via email to