about summary refs log tree commit diff
path: root/compiler/rustc_expand/src/expand.rs
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2025-08-09 23:56:00 -0700
committerJosh Triplett <josh@joshtriplett.org>2025-08-14 14:23:05 -0700
commit354fcf2b52119d938b3181bd6cbc3be1929138df (patch)
tree6ef9a562d362b3db77d85520820570bcc342c73b /compiler/rustc_expand/src/expand.rs
parent8fb98ef36846f74c8a642e856808ad5600ae4110 (diff)
downloadrust-354fcf2b52119d938b3181bd6cbc3be1929138df.tar.gz
rust-354fcf2b52119d938b3181bd6cbc3be1929138df.zip
mbe: Handle applying `macro_rules` derives
Add infrastructure to apply a derive macro to arguments, consuming and
returning a `TokenTree` only.

Handle `SyntaxExtensionKind::MacroRules` when expanding a derive, if the
macro's kinds support derive.

Add tests covering various cases of `macro_rules` derives.

Note that due to a pre-existing FIXME in `expand.rs`, derives are
re-queued and some errors get emitted twice. Duplicate diagnostic
suppression makes them not visible, but the FIXME should still get
fixed.
Diffstat (limited to 'compiler/rustc_expand/src/expand.rs')
-rw-r--r--compiler/rustc_expand/src/expand.rs31
1 files changed, 31 insertions, 0 deletions
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 670f5c91bb9..1f7f4c7d856 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -16,6 +16,7 @@ use rustc_attr_parsing::{EvalConfigResult, ShouldEmit};
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_errors::PResult;
 use rustc_feature::Features;
+use rustc_hir::def::MacroKinds;
 use rustc_parse::parser::{
     AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
     token_descr,
@@ -565,6 +566,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                 .map(|DeriveResolution { path, item, exts: _, is_const }| {
                                     // FIXME: Consider using the derive resolutions (`_exts`)
                                     // instead of enqueuing the derives to be resolved again later.
+                                    // Note that this can result in duplicate diagnostics.
                                     let expn_id = LocalExpnId::fresh_empty();
                                     derive_invocations.push((
                                         Invocation {
@@ -922,6 +924,35 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     }
                     fragment
                 }
+                SyntaxExtensionKind::MacroRules(expander)
+                    if expander.kinds().contains(MacroKinds::DERIVE) =>
+                {
+                    if is_const {
+                        let guar = self
+                            .cx
+                            .dcx()
+                            .span_err(span, "macro `derive` does not support const derives");
+                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));
+                    }
+                    let body = item.to_tokens();
+                    match expander.expand_derive(self.cx, span, &body) {
+                        Ok(tok_result) => {
+                            let fragment =
+                                self.parse_ast_fragment(tok_result, fragment_kind, &path, span);
+                            if macro_stats {
+                                update_derive_macro_stats(
+                                    self.cx,
+                                    fragment_kind,
+                                    span,
+                                    &path,
+                                    &fragment,
+                                );
+                            }
+                            fragment
+                        }
+                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
+                    }
+                }
                 _ => unreachable!(),
             },
             InvocationKind::GlobDelegation { item, of_trait } => {