hir_expand/
db.rs

1//! Defines database & queries for macro expansion.
2
3use base_db::{Crate, RootQueryDb};
4use mbe::MatchedArmIndex;
5use span::{AstIdMap, Edition, Span, SyntaxContext};
6use syntax::{AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, ast};
7use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree};
8use triomphe::Arc;
9
10use crate::{
11    AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
12    EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, HirFileId, MacroCallId,
13    MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
14    attrs::Meta,
15    builtin::pseudo_derive_attr_expansion,
16    cfg_process::attr_macro_input_to_token_tree,
17    declarative::DeclarativeMacroExpander,
18    fixup::{self, SyntaxFixupUndoInfo},
19    hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt},
20    proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros},
21    span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
22    tt,
23};
24/// This is just to ensure the types of smart_macro_arg and macro_arg are the same
25type MacroArgResult = (Arc<tt::TopSubtree>, SyntaxFixupUndoInfo, Span);
26/// Total limit on the number of tokens produced by any macro invocation.
27///
28/// If an invocation produces more tokens than this limit, it will not be stored in the database and
29/// an error will be emitted.
30///
31/// Actual max for `analysis-stats .` at some point: 30672.
32const TOKEN_LIMIT: usize = 2_097_152;
33
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub enum TokenExpander {
36    /// Old-style `macro_rules` or the new macros 2.0
37    DeclarativeMacro(Arc<DeclarativeMacroExpander>),
38    /// Stuff like `line!` and `file!`.
39    BuiltIn(BuiltinFnLikeExpander),
40    /// Built-in eagerly expanded fn-like macros (`include!`, `concat!`, etc.)
41    BuiltInEager(EagerExpander),
42    /// `global_allocator` and such.
43    BuiltInAttr(BuiltinAttrExpander),
44    /// `derive(Copy)` and such.
45    BuiltInDerive(BuiltinDeriveExpander),
46    /// The thing we love the most here in rust-analyzer -- procedural macros.
47    ProcMacro(CustomProcMacroExpander),
48}
49
50#[query_group::query_group]
51pub trait ExpandDatabase: RootQueryDb {
52    /// The proc macros. Do not use this! Use `proc_macros_for_crate()` instead.
53    #[salsa::input]
54    fn proc_macros(&self) -> Arc<ProcMacros>;
55
56    /// Incrementality query to prevent queries from directly depending on `ExpandDatabase::proc_macros`.
57    #[salsa::invoke(crate::proc_macro::proc_macros_for_crate)]
58    fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>;
59
60    #[salsa::invoke(ast_id_map)]
61    #[salsa::lru(1024)]
62    fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
63
64    #[salsa::transparent]
65    fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode;
66
67    /// Implementation for the macro case.
68    #[salsa::lru(512)]
69    fn parse_macro_expansion(
70        &self,
71        macro_file: MacroCallId,
72    ) -> ExpandResult<(Parse<SyntaxNode>, Arc<ExpansionSpanMap>)>;
73
74    #[salsa::transparent]
75    #[salsa::invoke(SpanMap::new)]
76    fn span_map(&self, file_id: HirFileId) -> SpanMap;
77
78    #[salsa::transparent]
79    #[salsa::invoke(crate::span_map::expansion_span_map)]
80    fn expansion_span_map(&self, file_id: MacroCallId) -> Arc<ExpansionSpanMap>;
81    #[salsa::invoke(crate::span_map::real_span_map)]
82    fn real_span_map(&self, file_id: EditionedFileId) -> Arc<RealSpanMap>;
83
84    /// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the
85    /// reason why we use salsa at all.
86    ///
87    /// We encode macro definitions into ids of macro calls, this what allows us
88    /// to be incremental.
89    #[salsa::transparent]
90    fn intern_macro_call(&self, macro_call: MacroCallLoc) -> MacroCallId;
91    #[salsa::transparent]
92    fn lookup_intern_macro_call(&self, macro_call: MacroCallId) -> MacroCallLoc;
93
94    /// Lowers syntactic macro call to a token tree representation. That's a firewall
95    /// query, only typing in the macro call itself changes the returned
96    /// subtree.
97    #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"]
98    #[salsa::invoke(macro_arg)]
99    fn macro_arg(&self, id: MacroCallId) -> MacroArgResult;
100
101    #[salsa::transparent]
102    fn macro_arg_considering_derives(
103        &self,
104        id: MacroCallId,
105        kind: &MacroCallKind,
106    ) -> MacroArgResult;
107
108    /// Fetches the expander for this macro.
109    #[salsa::transparent]
110    #[salsa::invoke(TokenExpander::macro_expander)]
111    fn macro_expander(&self, id: MacroDefId) -> TokenExpander;
112
113    /// Fetches (and compiles) the expander of this decl macro.
114    #[salsa::invoke(DeclarativeMacroExpander::expander)]
115    fn decl_macro_expander(
116        &self,
117        def_crate: Crate,
118        id: AstId<ast::Macro>,
119    ) -> Arc<DeclarativeMacroExpander>;
120
121    /// Special case of the previous query for procedural macros. We can't LRU
122    /// proc macros, since they are not deterministic in general, and
123    /// non-determinism breaks salsa in a very, very, very bad way.
124    /// @edwin0cheng heroically debugged this once! See #4315 for details
125    #[salsa::invoke(expand_proc_macro)]
126    fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<Arc<tt::TopSubtree>>;
127    /// Retrieves the span to be used for a proc-macro expansions spans.
128    /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to
129    /// directly depend on as that would cause to frequent invalidations, mainly because of the
130    /// parse queries being LRU cached. If they weren't the invalidations would only happen if the
131    /// user wrote in the file that defines the proc-macro.
132    #[salsa::invoke_interned(proc_macro_span)]
133    fn proc_macro_span(&self, fun: AstId<ast::Fn>) -> Span;
134
135    /// Firewall query that returns the errors from the `parse_macro_expansion` query.
136    #[salsa::invoke(parse_macro_expansion_error)]
137    fn parse_macro_expansion_error(
138        &self,
139        macro_call: MacroCallId,
140    ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
141
142    #[salsa::transparent]
143    fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
144}
145
146#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext, revisions = usize::MAX)]
147pub struct SyntaxContextWrapper {
148    pub data: SyntaxContext,
149}
150
151fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContext {
152    match file {
153        HirFileId::FileId(_) => SyntaxContext::root(edition),
154        HirFileId::MacroFile(m) => {
155            let kind = db.lookup_intern_macro_call(m).kind;
156            db.macro_arg_considering_derives(m, &kind).2.ctx
157        }
158    }
159}
160
161/// This expands the given macro call, but with different arguments. This is
162/// used for completion, where we want to see what 'would happen' if we insert a
163/// token. The `token_to_map` mapped down into the expansion, with the mapped
164/// token(s) returned with their priority.
165pub fn expand_speculative(
166    db: &dyn ExpandDatabase,
167    actual_macro_call: MacroCallId,
168    speculative_args: &SyntaxNode,
169    token_to_map: SyntaxToken,
170) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
171    let loc = db.lookup_intern_macro_call(actual_macro_call);
172    let (_, _, span) = db.macro_arg_considering_derives(actual_macro_call, &loc.kind);
173
174    let span_map = RealSpanMap::absolute(span.anchor.file_id);
175    let span_map = SpanMapRef::RealSpanMap(&span_map);
176
177    // Build the subtree and token mapping for the speculative args
178    let (mut tt, undo_info) = match &loc.kind {
179        MacroCallKind::FnLike { .. } => (
180            syntax_bridge::syntax_node_to_token_tree(
181                speculative_args,
182                span_map,
183                span,
184                if loc.def.is_proc_macro() {
185                    DocCommentDesugarMode::ProcMacro
186                } else {
187                    DocCommentDesugarMode::Mbe
188                },
189            ),
190            SyntaxFixupUndoInfo::NONE,
191        ),
192        MacroCallKind::Attr { .. } if loc.def.is_attribute_derive() => (
193            syntax_bridge::syntax_node_to_token_tree(
194                speculative_args,
195                span_map,
196                span,
197                DocCommentDesugarMode::ProcMacro,
198            ),
199            SyntaxFixupUndoInfo::NONE,
200        ),
201        MacroCallKind::Derive { derive_macro_id, .. } => {
202            let MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } =
203                &derive_macro_id.loc(db).kind
204            else {
205                unreachable!("`derive_macro_id` should be `MacroCallKind::Attr`");
206            };
207            attr_macro_input_to_token_tree(
208                db,
209                speculative_args,
210                span_map,
211                span,
212                true,
213                attr_ids,
214                loc.krate,
215            )
216        }
217        MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } => attr_macro_input_to_token_tree(
218            db,
219            speculative_args,
220            span_map,
221            span,
222            false,
223            attr_ids,
224            loc.krate,
225        ),
226    };
227
228    let attr_arg = match &loc.kind {
229        MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } => {
230            if loc.def.is_attribute_derive() {
231                // for pseudo-derive expansion we actually pass the attribute itself only
232                ast::Attr::cast(speculative_args.clone()).and_then(|attr| attr.token_tree()).map(
233                    |token_tree| {
234                        let mut tree = syntax_node_to_token_tree(
235                            token_tree.syntax(),
236                            span_map,
237                            span,
238                            DocCommentDesugarMode::ProcMacro,
239                        );
240                        *tree.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span);
241                        tree
242                    },
243                )
244            } else {
245                // Attributes may have an input token tree, build the subtree and map for this as well
246                // then try finding a token id for our token if it is inside this input subtree.
247                let item = ast::Item::cast(speculative_args.clone())?;
248                let (_, _, _, meta) =
249                    attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &item);
250                match meta {
251                    Meta::TokenTree { tt, .. } => {
252                        let mut attr_arg = syntax_bridge::syntax_node_to_token_tree(
253                            tt.syntax(),
254                            span_map,
255                            span,
256                            DocCommentDesugarMode::ProcMacro,
257                        );
258                        attr_arg.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
259                        Some(attr_arg)
260                    }
261                    _ => None,
262                }
263            }
264        }
265        _ => None,
266    };
267
268    // Do the actual expansion, we need to directly expand the proc macro due to the attribute args
269    // Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
270    let mut speculative_expansion = match loc.def.kind {
271        MacroDefKind::ProcMacro(ast, expander, _) => {
272            let span = db.proc_macro_span(ast);
273            *tt.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span);
274            expander.expand(
275                db,
276                loc.def.krate,
277                loc.krate,
278                &tt,
279                attr_arg.as_ref(),
280                span_with_def_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition),
281                span_with_call_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition),
282                span_with_mixed_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition),
283            )
284        }
285        MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
286            pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span)
287        }
288        MacroDefKind::Declarative(it, _) => db
289            .decl_macro_expander(loc.krate, it)
290            .expand_unhygienic(db, tt, loc.kind.call_style(), span),
291        MacroDefKind::BuiltIn(_, it) => {
292            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
293        }
294        MacroDefKind::BuiltInDerive(_, it) => {
295            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
296        }
297        MacroDefKind::BuiltInEager(_, it) => {
298            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
299        }
300        MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
301    };
302
303    let expand_to = loc.expand_to();
304
305    fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info);
306    let (node, rev_tmap) = token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to);
307
308    let syntax_node = node.syntax_node();
309    let token = rev_tmap
310        .ranges_with_span(span_map.span_for_range(token_to_map.text_range()))
311        .filter_map(|(range, ctx)| syntax_node.covering_element(range).into_token().zip(Some(ctx)))
312        .map(|(t, ctx)| {
313            // prefer tokens of the same kind and text, as well as non opaque marked ones
314            // Note the inversion of the score here, as we want to prefer the first token in case
315            // of all tokens having the same score
316            let ranking = ctx.is_opaque(db) as u8
317                + 2 * (t.kind() != token_to_map.kind()) as u8
318                + 4 * ((t.text() != token_to_map.text()) as u8);
319            (t, ranking)
320        })
321        .collect();
322    Some((node.syntax_node(), token))
323}
324
325fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> triomphe::Arc<AstIdMap> {
326    triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id)))
327}
328
329/// Main public API -- parses a hir file, not caring whether it's a real
330/// file or a macro expansion.
331fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode {
332    match file_id {
333        HirFileId::FileId(file_id) => db.parse(file_id).syntax_node(),
334        HirFileId::MacroFile(macro_file) => {
335            db.parse_macro_expansion(macro_file).value.0.syntax_node()
336        }
337    }
338}
339
340// FIXME: We should verify that the parsed node is one of the many macro node variants we expect
341// instead of having it be untyped
342fn parse_macro_expansion(
343    db: &dyn ExpandDatabase,
344    macro_file: MacroCallId,
345) -> ExpandResult<(Parse<SyntaxNode>, Arc<ExpansionSpanMap>)> {
346    let _p = tracing::info_span!("parse_macro_expansion").entered();
347    let loc = db.lookup_intern_macro_call(macro_file);
348    let expand_to = loc.expand_to();
349    let mbe::ValueResult { value: (tt, matched_arm), err } = macro_expand(db, macro_file, loc);
350
351    let (parse, mut rev_token_map) = token_tree_to_syntax_node(
352        db,
353        match &tt {
354            CowArc::Arc(it) => it,
355            CowArc::Owned(it) => it,
356        },
357        expand_to,
358    );
359    rev_token_map.matched_arm = matched_arm;
360
361    ExpandResult { value: (parse, Arc::new(rev_token_map)), err }
362}
363
364fn parse_macro_expansion_error(
365    db: &dyn ExpandDatabase,
366    macro_call_id: MacroCallId,
367) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>> {
368    let e: ExpandResult<Arc<[SyntaxError]>> =
369        db.parse_macro_expansion(macro_call_id).map(|it| Arc::from(it.0.errors()));
370    if e.value.is_empty() && e.err.is_none() { None } else { Some(Arc::new(e)) }
371}
372
373pub(crate) fn parse_with_map(
374    db: &dyn ExpandDatabase,
375    file_id: HirFileId,
376) -> (Parse<SyntaxNode>, SpanMap) {
377    match file_id {
378        HirFileId::FileId(file_id) => {
379            (db.parse(file_id).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id)))
380        }
381        HirFileId::MacroFile(macro_file) => {
382            let (parse, map) = db.parse_macro_expansion(macro_file).value;
383            (parse, SpanMap::ExpansionSpanMap(map))
384        }
385    }
386}
387
388/// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
389/// Other wise return the [macro_arg] for the macro_call_id.
390///
391/// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is
392#[allow(deprecated)] // we are macro_arg_considering_derives
393fn macro_arg_considering_derives(
394    db: &dyn ExpandDatabase,
395    id: MacroCallId,
396    kind: &MacroCallKind,
397) -> MacroArgResult {
398    match kind {
399        // Get the macro arg for the derive macro
400        MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(*derive_macro_id),
401        // Normal macro arg
402        _ => db.macro_arg(id),
403    }
404}
405
406fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
407    let loc = db.lookup_intern_macro_call(id);
408
409    if let MacroCallLoc {
410        def: MacroDefId { kind: MacroDefKind::BuiltInEager(..), .. },
411        kind: MacroCallKind::FnLike { eager: Some(eager), .. },
412        ..
413    } = &loc
414    {
415        return (eager.arg.clone(), SyntaxFixupUndoInfo::NONE, eager.span);
416    }
417
418    let (parse, map) = parse_with_map(db, loc.kind.file_id());
419    let root = parse.syntax_node();
420
421    let (is_derive, censor_item_tree_attr_ids, item_node, span) = match &loc.kind {
422        MacroCallKind::FnLike { ast_id, .. } => {
423            let node = &ast_id.to_ptr(db).to_node(&root);
424            let path_range = node
425                .path()
426                .map_or_else(|| node.syntax().text_range(), |path| path.syntax().text_range());
427            let span = map.span_for_range(path_range);
428
429            let dummy_tt = |kind| {
430                (
431                    Arc::new(tt::TopSubtree::from_token_trees(
432                        tt::Delimiter { open: span, close: span, kind },
433                        tt::TokenTreesView::new(&[]),
434                    )),
435                    SyntaxFixupUndoInfo::default(),
436                    span,
437                )
438            };
439
440            let Some(tt) = node.token_tree() else {
441                return dummy_tt(tt::DelimiterKind::Invisible);
442            };
443            let first = tt.left_delimiter_token().map(|it| it.kind()).unwrap_or(T!['(']);
444            let last = tt.right_delimiter_token().map(|it| it.kind()).unwrap_or(T![.]);
445
446            let mismatched_delimiters = !matches!(
447                (first, last),
448                (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}'])
449            );
450            if mismatched_delimiters {
451                // Don't expand malformed (unbalanced) macro invocations. This is
452                // less than ideal, but trying to expand unbalanced  macro calls
453                // sometimes produces pathological, deeply nested code which breaks
454                // all kinds of things.
455                //
456                // So instead, we'll return an empty subtree here
457                cov_mark::hit!(issue9358_bad_macro_stack_overflow);
458
459                let kind = match first {
460                    _ if loc.def.is_proc_macro() => tt::DelimiterKind::Invisible,
461                    T!['('] => tt::DelimiterKind::Parenthesis,
462                    T!['['] => tt::DelimiterKind::Bracket,
463                    T!['{'] => tt::DelimiterKind::Brace,
464                    _ => tt::DelimiterKind::Invisible,
465                };
466                return dummy_tt(kind);
467            }
468
469            let mut tt = syntax_bridge::syntax_node_to_token_tree(
470                tt.syntax(),
471                map.as_ref(),
472                span,
473                if loc.def.is_proc_macro() {
474                    DocCommentDesugarMode::ProcMacro
475                } else {
476                    DocCommentDesugarMode::Mbe
477                },
478            );
479            if loc.def.is_proc_macro() {
480                // proc macros expect their inputs without parentheses, MBEs expect it with them included
481                tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
482            }
483            return (Arc::new(tt), SyntaxFixupUndoInfo::NONE, span);
484        }
485        // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
486        MacroCallKind::Derive { .. } => {
487            unreachable!("`ExpandDatabase::macro_arg` called with `MacroCallKind::Derive`")
488        }
489        MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => {
490            let node = ast_id.to_ptr(db).to_node(&root);
491            let range = attr_ids
492                .invoc_attr()
493                .find_attr_range_with_source(db, loc.krate, &node)
494                .3
495                .path_range();
496            let span = map.span_for_range(range);
497
498            let is_derive = matches!(loc.def.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_derive());
499            (is_derive, &**attr_ids, node, span)
500        }
501    };
502
503    let (mut tt, undo_info) = attr_macro_input_to_token_tree(
504        db,
505        item_node.syntax(),
506        map.as_ref(),
507        span,
508        is_derive,
509        censor_item_tree_attr_ids,
510        loc.krate,
511    );
512
513    if loc.def.is_proc_macro() {
514        // proc macros expect their inputs without parentheses, MBEs expect it with them included
515        tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
516    }
517
518    (Arc::new(tt), undo_info, span)
519}
520
521impl TokenExpander {
522    fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander {
523        match id.kind {
524            MacroDefKind::Declarative(ast_id, _) => {
525                TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id))
526            }
527            MacroDefKind::BuiltIn(_, expander) => TokenExpander::BuiltIn(expander),
528            MacroDefKind::BuiltInAttr(_, expander) => TokenExpander::BuiltInAttr(expander),
529            MacroDefKind::BuiltInDerive(_, expander) => TokenExpander::BuiltInDerive(expander),
530            MacroDefKind::BuiltInEager(_, expander) => TokenExpander::BuiltInEager(expander),
531            MacroDefKind::ProcMacro(_, expander, _) => TokenExpander::ProcMacro(expander),
532        }
533    }
534}
535
536enum CowArc<T> {
537    Arc(Arc<T>),
538    Owned(T),
539}
540
541fn macro_expand(
542    db: &dyn ExpandDatabase,
543    macro_call_id: MacroCallId,
544    loc: MacroCallLoc,
545) -> ExpandResult<(CowArc<tt::TopSubtree>, MatchedArmIndex)> {
546    let _p = tracing::info_span!("macro_expand").entered();
547
548    let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
549        MacroDefKind::ProcMacro(..) => {
550            return db.expand_proc_macro(macro_call_id).map(CowArc::Arc).zip_val(None);
551        }
552        _ => {
553            let (macro_arg, undo_info, span) =
554                db.macro_arg_considering_derives(macro_call_id, &loc.kind);
555
556            let arg = &*macro_arg;
557            let res = match loc.def.kind {
558                MacroDefKind::Declarative(id, _) => db
559                    .decl_macro_expander(loc.def.krate, id)
560                    .expand(db, arg.clone(), macro_call_id, span),
561                MacroDefKind::BuiltIn(_, it) => {
562                    it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
563                }
564                MacroDefKind::BuiltInDerive(_, it) => {
565                    it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
566                }
567                MacroDefKind::BuiltInEager(_, it) => {
568                    // This might look a bit odd, but we do not expand the inputs to eager macros here.
569                    // Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
570                    // That kind of expansion uses the ast id map of an eager macros input though which goes through
571                    // the HirFileId machinery. As eager macro inputs are assigned a macro file id that query
572                    // will end up going through here again, whereas we want to just want to inspect the raw input.
573                    // As such we just return the input subtree here.
574                    let eager = match &loc.kind {
575                        MacroCallKind::FnLike { eager: None, .. } => {
576                            return ExpandResult::ok(CowArc::Arc(macro_arg.clone())).zip_val(None);
577                        }
578                        MacroCallKind::FnLike { eager: Some(eager), .. } => Some(&**eager),
579                        _ => None,
580                    };
581
582                    let mut res = it.expand(db, macro_call_id, arg, span).map_err(Into::into);
583
584                    if let Some(EagerCallInfo { error, .. }) = eager {
585                        // FIXME: We should report both errors!
586                        res.err = error.clone().or(res.err);
587                    }
588                    res.zip_val(None)
589                }
590                MacroDefKind::BuiltInAttr(_, it) => {
591                    let mut res = it.expand(db, macro_call_id, arg, span);
592                    fixup::reverse_fixups(&mut res.value, &undo_info);
593                    res.zip_val(None)
594                }
595                MacroDefKind::ProcMacro(_, _, _) => unreachable!(),
596            };
597            (ExpandResult { value: res.value, err: res.err }, span)
598        }
599    };
600
601    // Skip checking token tree limit for include! macro call
602    if !loc.def.is_include() {
603        // Set a hard limit for the expanded tt
604        if let Err(value) = check_tt_count(&tt) {
605            return value
606                .map(|()| CowArc::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))))
607                .zip_val(matched_arm);
608        }
609    }
610
611    ExpandResult { value: (CowArc::Owned(tt), matched_arm), err }
612}
613
614fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
615    let root = db.parse_or_expand(ast.file_id);
616    let ast_id_map = &db.ast_id_map(ast.file_id);
617    let span_map = &db.span_map(ast.file_id);
618
619    let node = ast_id_map.get(ast.value).to_node(&root);
620    let range = ast::HasName::name(&node)
621        .map_or_else(|| node.syntax().text_range(), |name| name.syntax().text_range());
622    span_map.span_for_range(range)
623}
624
625fn expand_proc_macro(
626    db: &dyn ExpandDatabase,
627    id: MacroCallId,
628) -> ExpandResult<Arc<tt::TopSubtree>> {
629    let loc = db.lookup_intern_macro_call(id);
630    let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(id, &loc.kind);
631
632    let (ast, expander) = match loc.def.kind {
633        MacroDefKind::ProcMacro(ast, expander, _) => (ast, expander),
634        _ => unreachable!(),
635    };
636
637    let attr_arg = match &loc.kind {
638        MacroCallKind::Attr { attr_args: Some(attr_args), .. } => Some(&**attr_args),
639        _ => None,
640    };
641
642    let ExpandResult { value: mut tt, err } = {
643        let span = db.proc_macro_span(ast);
644        expander.expand(
645            db,
646            loc.def.krate,
647            loc.krate,
648            &macro_arg,
649            attr_arg,
650            span_with_def_site_ctxt(db, span, id.into(), loc.def.edition),
651            span_with_call_site_ctxt(db, span, id.into(), loc.def.edition),
652            span_with_mixed_site_ctxt(db, span, id.into(), loc.def.edition),
653        )
654    };
655
656    // Set a hard limit for the expanded tt
657    if let Err(value) = check_tt_count(&tt) {
658        return value.map(|()| Arc::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))));
659    }
660
661    fixup::reverse_fixups(&mut tt, &undo_info);
662
663    ExpandResult { value: Arc::new(tt), err }
664}
665
666pub(crate) fn token_tree_to_syntax_node(
667    db: &dyn ExpandDatabase,
668    tt: &tt::TopSubtree,
669    expand_to: ExpandTo,
670) -> (Parse<SyntaxNode>, ExpansionSpanMap) {
671    let entry_point = match expand_to {
672        ExpandTo::Statements => syntax_bridge::TopEntryPoint::MacroStmts,
673        ExpandTo::Items => syntax_bridge::TopEntryPoint::MacroItems,
674        ExpandTo::Pattern => syntax_bridge::TopEntryPoint::Pattern,
675        ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
676        ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
677    };
678    syntax_bridge::token_tree_to_syntax_node(tt, entry_point, &mut |ctx| ctx.edition(db))
679}
680
681fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
682    let tt = tt.top_subtree();
683    let count = tt.count();
684    if count <= TOKEN_LIMIT {
685        Ok(())
686    } else {
687        Err(ExpandResult {
688            value: (),
689            err: Some(ExpandError::other(
690                tt.delimiter.open,
691                format!(
692                    "macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}",
693                ),
694            )),
695        })
696    }
697}
698
699fn intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallLoc) -> MacroCallId {
700    MacroCallId::new(db, macro_call)
701}
702
703fn lookup_intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallId) -> MacroCallLoc {
704    macro_call.loc(db)
705}