Skip to main content

hir_def/nameres/
collector.rs

1//! The core of the module-level name resolution algorithm.
2//!
3//! `DefCollector::collect` contains the fixed-point iteration loop which
4//! resolves imports and expands macros.
5
6use std::{iter, mem, ops::Range};
7
8use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin, SourceDatabase};
9use cfg::{CfgAtom, CfgExpr, CfgOptions};
10use either::Either;
11use hir_expand::{
12    AttrMacroAttrIds, EditionedFileId, ErasedAstId, ExpandTo, HirFileId, InFile, MacroCallId,
13    MacroCallKind, MacroDefId, MacroDefKind,
14    attrs::{Attr, AttrId},
15    builtin::{BuiltinDeriveExpander, find_builtin_attr, find_builtin_derive, find_builtin_macro},
16    mod_path::{ModPath, PathKind},
17    name::{AsName, Name},
18    proc_macro::{CustomProcMacroExpander, ProcMacros},
19};
20use intern::{Interned, Symbol, sym};
21use itertools::izip;
22use la_arena::Idx;
23use rustc_hash::{FxHashMap, FxHashSet};
24use smallvec::SmallVec;
25use span::{Edition, FileAstId, ROOT_ERASED_FILE_AST_ID, SyntaxContext};
26use stdx::always;
27use syntax::ast;
28use triomphe::Arc;
29
30use crate::{
31    AdtId, AssocItemId, AstId, AstIdWithPath, BuiltinDeriveImplId, BuiltinDeriveImplLoc, ConstLoc,
32    EnumLoc, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, FxIndexMap,
33    ImplLoc, Intern, ItemContainerId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
34    MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
35    ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId,
36    UseLoc, file_item_tree,
37    item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
38    item_tree::{
39        self, Attrs, AttrsOrCfg, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2,
40        MacroCall, MacroRules, Mod, ModItemId, ModItemKind, ModKind, StructValueNsCtor, TreeId,
41        Use,
42    },
43    macro_call_as_call_id,
44    nameres::{
45        BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
46        assoc::TraitItems,
47        attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
48        crate_def_map,
49        diagnostics::DefDiagnostic,
50        mod_resolution::ModDir,
51        path_resolution::{ReachedFixedPoint, ResolvePathResult},
52        proc_macro::{ProcMacroDef, ProcMacroKind, parse_macro_name_and_helper_attrs},
53        sub_namespace_match,
54    },
55    per_ns::{Item, PerNs},
56    tt,
57    visibility::{RawVisibility, Visibility},
58};
59
60const GLOB_RECURSION_LIMIT: usize = 100;
61const FIXED_POINT_LIMIT: usize = 8192;
62
63pub(super) fn collect_defs(
64    db: &dyn SourceDatabase,
65    def_map: DefMap,
66    tree_id: TreeId,
67    crate_local_def_map: Option<&LocalDefMap>,
68) -> (DefMap, LocalDefMap) {
69    let krate = &def_map.krate.data(db);
70    let cfg_options = def_map.krate.cfg_options(db);
71
72    // populate external prelude and dependency list
73    let mut deps =
74        FxIndexMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
75    for dep in &krate.dependencies {
76        tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
77
78        deps.insert(dep.as_name(), dep.clone());
79    }
80
81    let proc_macros = if krate.target_kind.is_proc_macro() {
82        ProcMacros::get_for_crate(db, def_map.krate)
83            .and_then(|proc_macros| {
84                proc_macros.list(tree_id.file_id().syntax_context(db, krate.edition))
85            })
86            .unwrap_or_default()
87    } else {
88        Default::default()
89    };
90
91    let mut collector = DefCollector {
92        db,
93        def_map,
94        local_def_map: LocalDefMap::default(),
95        crate_local_def_map,
96        deps,
97        glob_imports: FxHashMap::default(),
98        unresolved_imports: Vec::new(),
99        indeterminate_imports: Vec::new(),
100        unresolved_macros: Vec::new(),
101        mod_dirs: FxHashMap::default(),
102        cfg_options,
103        proc_macros,
104        from_glob_import: Default::default(),
105        skip_attrs: Default::default(),
106        prev_active_attrs: Default::default(),
107        unresolved_extern_crates: Default::default(),
108        is_proc_macro: krate.target_kind.is_proc_macro(),
109        deferred_builtin_derives: Default::default(),
110    };
111    if tree_id.is_block() {
112        collector.seed_with_inner(tree_id);
113    } else {
114        collector.seed_with_top_level();
115    }
116    collector.collect();
117    let (mut def_map, mut local_def_map) = collector.finish();
118    def_map.shrink_to_fit();
119    local_def_map.shrink_to_fit();
120    (def_map, local_def_map)
121}
122
123#[derive(Copy, Clone, Debug, Eq, PartialEq)]
124enum PartialResolvedImport {
125    /// None of any namespaces is resolved
126    Unresolved,
127    /// One of namespaces is resolved
128    Indeterminate(PerNs),
129    /// All namespaces are resolved, OR it comes from other crate
130    Resolved(PerNs),
131}
132
133impl PartialResolvedImport {
134    fn namespaces(self) -> PerNs {
135        match self {
136            PartialResolvedImport::Unresolved => PerNs::none(),
137            PartialResolvedImport::Indeterminate(ns) | PartialResolvedImport::Resolved(ns) => ns,
138        }
139    }
140}
141
142#[derive(Clone, Debug, Eq, PartialEq)]
143struct ImportSource {
144    use_tree: Idx<ast::UseTree>,
145    id: UseId,
146    is_prelude: bool,
147    kind: ImportKind,
148}
149
150#[derive(Debug, Eq, PartialEq)]
151struct Import {
152    path: ModPath,
153    alias: Option<ImportAlias>,
154    visibility: RawVisibility,
155    source: ImportSource,
156}
157
158impl Import {
159    fn from_use(
160        tree: &ItemTree,
161        item: &Use,
162        id: UseId,
163        is_prelude: bool,
164        mut cb: impl FnMut(Self),
165    ) {
166        let visibility = &tree[item.visibility];
167        item.expand(|idx, path, kind, alias| {
168            cb(Self {
169                path,
170                alias,
171                visibility: visibility.clone(),
172                source: ImportSource { use_tree: idx, id, is_prelude, kind },
173            });
174        });
175    }
176}
177
178#[derive(Debug, Eq, PartialEq)]
179struct ImportDirective {
180    /// The module this import directive is in.
181    module_id: ModuleId,
182    import: Import,
183    status: PartialResolvedImport,
184}
185
186#[derive(Clone, Debug, Eq, PartialEq)]
187struct MacroDirective<'db> {
188    module_id: ModuleId,
189    depth: u32,
190    kind: MacroDirectiveKind<'db>,
191    container: ItemContainerId,
192}
193
194#[derive(Clone, Debug, Eq, PartialEq)]
195enum MacroDirectiveKind<'db> {
196    FnLike {
197        ast_id: AstIdWithPath<ast::MacroCall>,
198        expand_to: ExpandTo,
199        ctxt: SyntaxContext,
200    },
201    Derive {
202        ast_id: AstIdWithPath<ast::Adt>,
203        derive_attr: AttrId,
204        derive_pos: usize,
205        ctxt: SyntaxContext,
206        /// The "parent" macro it is resolved to.
207        derive_macro_id: MacroCallId,
208    },
209    Attr {
210        ast_id: AstIdWithPath<ast::Item>,
211        attr_id: AttrId,
212        attr: Attr,
213        mod_item: ModItemId,
214        /* is this needed? */ tree: TreeId,
215        item_tree: &'db ItemTree,
216    },
217}
218
219#[derive(Debug)]
220struct DeferredBuiltinDerive {
221    call_id: MacroCallId,
222    derive: BuiltinDeriveExpander,
223    module_id: ModuleId,
224    depth: u32,
225    container: ItemContainerId,
226    derive_attr_id: AttrId,
227    derive_index: u32,
228    helpers_range: Range<usize>,
229}
230
231/// Walks the tree of module recursively
232struct DefCollector<'db> {
233    db: &'db dyn SourceDatabase,
234    def_map: DefMap,
235    local_def_map: LocalDefMap,
236    /// Set only in case of blocks.
237    crate_local_def_map: Option<&'db LocalDefMap>,
238    // The dependencies of the current crate, including optional deps like `test`.
239    deps: FxIndexMap<Name, BuiltDependency>,
240    glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, Visibility, GlobId)>>,
241    unresolved_imports: Vec<ImportDirective>,
242    indeterminate_imports: Vec<(ImportDirective, PerNs)>,
243    unresolved_macros: Vec<MacroDirective<'db>>,
244    // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
245    // resolve. When we emit diagnostics for unresolved imports, we only do so if the import
246    // doesn't start with an unresolved crate's name.
247    unresolved_extern_crates: FxHashSet<Name>,
248    mod_dirs: FxHashMap<ModuleId, ModDir>,
249    cfg_options: &'db CfgOptions,
250    /// List of procedural macros defined by this crate. This is read from the dynamic library
251    /// built by the build system, and is the list of proc-macros we can actually expand. It is
252    /// empty when proc-macro support is disabled (in which case we still do name resolution for
253    /// them). The bool signals whether the proc-macro has been explicitly disabled for name-resolution.
254    proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>,
255    is_proc_macro: bool,
256    from_glob_import: PerNsGlobImports,
257    /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
258    /// This map is used to skip all attributes up to and including the one that failed to resolve,
259    /// in order to not expand them twice.
260    ///
261    /// This also stores the attributes to skip when we resolve derive helpers and non-macro
262    /// non-builtin attributes in general.
263    // FIXME: There has to be a better way to do this
264    skip_attrs: FxHashMap<InFile<ModItemId>, AttrId>,
265    /// When we expand attributes, we need to censor all previous active attributes
266    /// on the same item. Therefore, this holds all active attributes that we already
267    /// expanded.
268    prev_active_attrs: FxHashMap<AstId<ast::Item>, SmallVec<[AttrId; 1]>>,
269    /// To save memory, we do not really expand builtin derives. Instead, we save them as a `BuiltinDeriveImplId`.
270    ///
271    /// However, we can only do that when the derive is directly above the item, and there is no attribute in between.
272    /// Otherwise, all sorts of weird things can happen, like the item name resolving to something else.
273    deferred_builtin_derives: FxHashMap<AstId<ast::Item>, Vec<DeferredBuiltinDerive>>,
274}
275
276impl<'db> DefCollector<'db> {
277    fn seed_with_top_level(&mut self) {
278        let _p = tracing::info_span!("seed_with_top_level").entered();
279
280        let file_id = self.def_map.krate.root_file_id(self.db);
281        let item_tree = file_item_tree(self.db, file_id.into(), self.def_map.krate);
282        let attrs = match item_tree.top_level_attrs() {
283            Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
284            None => Attrs::EMPTY,
285            Some(AttrsOrCfg::CfgDisabled(it)) => it.1.as_ref(),
286        };
287        let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
288
289        // Process other crate-level attributes.
290        for attr in &*attrs {
291            let Some(attr_name) = attr.path.as_ident() else { continue };
292
293            match () {
294                () if *attr_name == sym::recursion_limit => {
295                    if let Some(limit) = attr.string_value()
296                        && let Ok(limit) = limit.parse()
297                    {
298                        crate_data.recursion_limit = Some(limit);
299                    }
300                }
301                () if *attr_name == sym::crate_type => {
302                    if attr.string_value() == Some("proc-macro") {
303                        self.is_proc_macro = true;
304                    }
305                }
306                () if *attr_name == sym::no_core => crate_data.no_core = true,
307                () if *attr_name == sym::no_std => crate_data.no_std = true,
308                () if *attr_name == sym::rustc_coherence_is_core => {
309                    crate_data.rustc_coherence_is_core = true;
310                }
311                () if *attr_name == sym::feature => {
312                    let features =
313                        attr.parse_path_comma_token_tree(self.db).into_iter().flatten().filter_map(
314                            |(feat, _, _)| match feat.segments() {
315                                [name] => Some(name.symbol().clone()),
316                                _ => None,
317                            },
318                        );
319                    features.for_each(|feature| crate_data.unstable_features.enable(feature));
320                }
321                () if *attr_name == sym::register_tool => {
322                    if let Some(ident) = attr.single_ident_value() {
323                        crate_data.registered_tools.push(ident.sym.clone());
324                        cov_mark::hit!(register_tool);
325                    }
326                }
327                () => (),
328            }
329        }
330
331        for (name, dep) in &self.deps {
332            // Add all
333            if dep.is_prelude() {
334                // This is a bit confusing but the gist is that `no_core` and `no_std` remove the
335                // sysroot dependence on `core` and `std` respectively. Our `CrateGraph` is eagerly
336                // constructed with them in place no matter what though, since at that point we
337                // don't do pre-configured attribute resolution yet.
338                // So here check if we are no_core / no_std and we are trying to add the
339                // corresponding dep from the sysroot
340
341                // Depending on the crate data of a dependency seems bad for incrementality, but
342                // we only do that for sysroot crates (this is why the order of the `&&` is important)
343                // - which are normally standard library crate, which realistically aren't going
344                // to have their crate ID invalidated, because they stay on the same root file and
345                // they're dependencies of everything else, so if some collision miraculously occurs
346                // we will resolve it by disambiguating the other crate.
347                let skip = dep.is_sysroot()
348                    && match dep.crate_id.data(self.db).origin {
349                        CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
350                        CrateOrigin::Lang(LangCrateOrigin::Std) => {
351                            crate_data.no_core || crate_data.no_std
352                        }
353                        _ => false,
354                    };
355                if skip {
356                    continue;
357                }
358
359                // This eagerly draws a dependency edge between the crate def maps even if the
360                // things the crates are not used. This is not great, but at the same time we would
361                // like to compute our dependency def maps in parallel here anyways in the future
362                // which will have the same effect.
363                self.local_def_map.extern_prelude.insert(
364                    name.clone(),
365                    (crate_def_map(self.db, dep.crate_id).root_module_id(), None),
366                );
367            }
368        }
369
370        self.inject_prelude();
371
372        if let Some(AttrsOrCfg::CfgDisabled(attrs)) = item_tree.top_level_attrs() {
373            let (cfg_expr, _) = &**attrs;
374            self.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
375                self.def_map.root,
376                InFile::new(file_id.into(), ROOT_ERASED_FILE_AST_ID),
377                cfg_expr.clone(),
378                self.cfg_options.clone(),
379            ));
380            return;
381        }
382
383        let module_id = self.def_map.root;
384        ModCollector {
385            def_collector: self,
386            macro_depth: 0,
387            module_id,
388            tree_id: TreeId::new(file_id.into(), None),
389            item_tree,
390            mod_dir: ModDir::root(),
391        }
392        .collect_in_top_module(item_tree.top_level_items());
393        Arc::get_mut(&mut self.def_map.data).unwrap().shrink_to_fit();
394    }
395
396    fn seed_with_inner(&mut self, tree_id: TreeId) {
397        let item_tree = tree_id.item_tree(self.db, self.def_map.krate);
398        let is_cfg_enabled =
399            matches!(item_tree.top_level_attrs(), Some(AttrsOrCfg::Enabled { .. }) | None);
400        if is_cfg_enabled {
401            self.inject_prelude();
402
403            let module_id = self.def_map.root;
404            // A block `DefMap` is collected from scratch, but it may itself live inside a macro
405            // expansion. Continue that chain's budget instead of restarting it, or a macro
406            // expanding to an item that invokes the macro again never reaches the limit.
407            let macro_depth = tree_id.file_id().macro_expansion_depth(self.db);
408            ModCollector {
409                def_collector: self,
410                macro_depth,
411                module_id,
412                tree_id,
413                item_tree,
414                mod_dir: ModDir::root(),
415            }
416            .collect_in_top_module(item_tree.top_level_items());
417        }
418    }
419
420    fn resolution_loop(&mut self) {
421        let _p = tracing::info_span!("DefCollector::resolution_loop").entered();
422
423        // main name resolution fixed-point loop.
424        let mut i = 0;
425        'resolve_attr: loop {
426            let _p = tracing::info_span!("resolve_macros loop").entered();
427            'resolve_macros: loop {
428                self.db.unwind_if_revision_cancelled();
429
430                {
431                    let _p = tracing::info_span!("resolve_imports loop").entered();
432
433                    'resolve_imports: loop {
434                        if self.resolve_imports() == ReachedFixedPoint::Yes {
435                            break 'resolve_imports;
436                        }
437                    }
438                }
439                if self.resolve_macros() == ReachedFixedPoint::Yes {
440                    break 'resolve_macros;
441                }
442
443                i += 1;
444                if i > FIXED_POINT_LIMIT {
445                    tracing::error!("name resolution is stuck");
446                    break 'resolve_attr;
447                }
448            }
449
450            if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
451                break 'resolve_attr;
452            }
453        }
454    }
455
456    fn collect(&mut self) {
457        let _p = tracing::info_span!("DefCollector::collect").entered();
458
459        self.resolution_loop();
460
461        let unresolved_imports = mem::take(&mut self.unresolved_imports);
462        // show unresolved imports in completion, etc
463        for directive in &unresolved_imports {
464            self.record_resolved_import(directive);
465        }
466        self.unresolved_imports = unresolved_imports;
467
468        if self.is_proc_macro {
469            // A crate exporting procedural macros is not allowed to export anything else.
470            //
471            // Additionally, while the proc macro entry points must be `pub`, they are not publicly
472            // exported in type/value namespace. This function reduces the visibility of all items
473            // in the crate root that aren't proc macros.
474            let module_id = self.def_map.root_module_id();
475            let root = &mut self.def_map.modules[module_id];
476            root.scope.censor_non_proc_macros(self.def_map.krate);
477        }
478    }
479
480    /// When the fixed-point loop reaches a stable state, we might still have
481    /// some unresolved attributes left over. This takes one of them, and feeds
482    /// the item it's applied to back into name resolution.
483    ///
484    /// This effectively ignores the fact that the macro is there and just treats the items as
485    /// normal code.
486    ///
487    /// This improves UX for unresolved attributes, and replicates the
488    /// behavior before we supported proc. attribute macros.
489    fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
490        cov_mark::hit!(unresolved_attribute_fallback);
491
492        let unresolved_attr =
493            self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
494                .kind
495            {
496                MacroDirectiveKind::Attr { ast_id, mod_item, attr_id, attr, tree, item_tree } => {
497                    self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
498                        directive.module_id,
499                        MacroCallKind::Attr {
500                            ast_id: ast_id.ast_id,
501                            attr_args: None,
502                            censored_attr_ids: AttrMacroAttrIds::from_one(*attr_id),
503                        },
504                        (*attr.path).clone(),
505                    ));
506
507                    self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr_id);
508
509                    Some((idx, directive, *mod_item, *tree, *item_tree))
510                }
511                _ => None,
512            });
513
514        match unresolved_attr {
515            Some((
516                pos,
517                &MacroDirective { module_id, depth, container, .. },
518                mod_item,
519                tree_id,
520                item_tree,
521            )) => {
522                // FIXME: Remove this clone
523                let mod_dir = self.mod_dirs[&module_id].clone();
524                ModCollector {
525                    def_collector: self,
526                    macro_depth: depth,
527                    module_id,
528                    tree_id,
529                    item_tree,
530                    mod_dir,
531                }
532                .collect(&[mod_item], container);
533
534                self.unresolved_macros.swap_remove(pos);
535                // Continue name resolution with the new data.
536                ReachedFixedPoint::No
537            }
538            None => ReachedFixedPoint::Yes,
539        }
540    }
541
542    fn inject_prelude(&mut self) {
543        // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
544
545        if self.def_map.data.no_core {
546            // libcore does not get a prelude.
547            return;
548        }
549
550        let krate = if self.def_map.data.no_std {
551            Name::new_symbol_root(sym::core)
552        } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std) {
553            Name::new_symbol_root(sym::std)
554        } else {
555            // If `std` does not exist for some reason, fall back to core. This mostly helps
556            // keep r-a's own tests minimal.
557            Name::new_symbol_root(sym::core)
558        };
559
560        let edition = match self.def_map.data.edition {
561            Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015),
562            Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018),
563            Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021),
564            Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024),
565        };
566
567        let path_kind = match self.def_map.data.edition {
568            Edition::Edition2015 => PathKind::Plain,
569            _ => PathKind::Abs,
570        };
571        let path = ModPath::from_segments(
572            path_kind,
573            [krate, Name::new_symbol_root(sym::prelude), edition],
574        );
575
576        let (per_ns, _) = self.def_map.resolve_path(
577            self.crate_local_def_map.unwrap_or(&self.local_def_map),
578            self.db,
579            self.def_map.root_module_id(),
580            &path,
581            BuiltinShadowMode::Other,
582            None,
583        );
584
585        match per_ns.types {
586            Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
587                self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
588            }
589            types => {
590                tracing::debug!(
591                    "could not resolve prelude path `{}` to module (resolved to {:?})",
592                    path.display(self.db, Edition::LATEST),
593                    types
594                );
595            }
596        }
597    }
598
599    fn local_def_map(&mut self) -> &LocalDefMap {
600        self.crate_local_def_map.unwrap_or(&self.local_def_map)
601    }
602
603    /// Adds a definition of procedural macro `name` to the root module.
604    ///
605    /// # Notes on procedural macro resolution
606    ///
607    /// Procedural macro functionality is provided by the build system: It has to build the proc
608    /// macro and pass the resulting dynamic library to rust-analyzer.
609    ///
610    /// When procedural macro support is enabled, the list of proc macros exported by a crate is
611    /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
612    /// derived from the dynamic library.
613    ///
614    /// However, we *also* would like to be able to at least *resolve* macros on our own, without
615    /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
616    /// use a dummy expander that always errors. This comes with the drawback of macros potentially
617    /// going out of sync with what the build system sees (since we resolve using VFS state, but
618    /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
619    fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>, fn_id: FunctionId) {
620        let kind = def.kind.to_basedb_kind();
621        let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) {
622            Some(_)
623                if kind == hir_expand::proc_macro::ProcMacroKind::Attr
624                    && !crate::ExpandProcAttrMacros::get(self.db).enabled(self.db) =>
625            {
626                (CustomProcMacroExpander::disabled_proc_attr(), kind)
627            }
628            Some(&(_, _, true)) => (CustomProcMacroExpander::disabled(), kind),
629            Some(&(_, expander, false)) => (expander, kind),
630            None => (CustomProcMacroExpander::missing_expander(), kind),
631        };
632
633        let proc_macro_id = ProcMacroLoc {
634            container: self.def_map.root_module_id(),
635            id: ast_id,
636            expander,
637            kind,
638            edition: self.def_map.data.edition,
639        }
640        .intern(self.db);
641
642        self.def_map.macro_def_to_macro_id.insert(ast_id.erase(), proc_macro_id.into());
643        self.define_proc_macro(def.name.clone(), proc_macro_id);
644        let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
645        if let ProcMacroKind::Derive { helpers } = def.kind {
646            crate_data.exported_derives.insert(proc_macro_id.into(), helpers);
647        }
648        crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
649        crate_data.fn_proc_macro_mapping_back.insert(proc_macro_id, fn_id);
650    }
651
652    /// Define a macro with `macro_rules`.
653    ///
654    /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
655    /// then it is also defined in the root module scope.
656    /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
657    ///
658    /// It is surprising that the macro will never be in the current module scope.
659    /// These code fails with "unresolved import/macro",
660    /// ```rust,compile_fail
661    /// mod m { macro_rules! foo { () => {} } }
662    /// use m::foo as bar;
663    /// ```
664    ///
665    /// ```rust,compile_fail
666    /// macro_rules! foo { () => {} }
667    /// self::foo!();
668    /// crate::foo!();
669    /// ```
670    ///
671    /// Well, this code compiles, because the plain path `foo` in `use` is searched
672    /// in the legacy textual scope only.
673    /// ```rust
674    /// macro_rules! foo { () => {} }
675    /// use foo as bar;
676    /// ```
677    fn define_macro_rules(
678        &mut self,
679        module_id: ModuleId,
680        name: Name,
681        macro_: MacroRulesId,
682        export: bool,
683    ) {
684        // Textual scoping
685        self.define_legacy_macro(module_id, name.clone(), macro_.into());
686
687        // Module scoping
688        // In Rust, `#[macro_export]` macros are unconditionally visible at the
689        // crate root, even if the parent modules is **not** visible.
690        if export {
691            let module_id = self.def_map.root;
692            self.def_map.modules[module_id].scope.declare(macro_.into());
693            self.update(
694                module_id,
695                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
696                Visibility::Public,
697                None,
698            );
699        }
700    }
701
702    /// Define a legacy textual scoped macro in module
703    ///
704    /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
705    /// It will clone all macros from parent legacy scope, whose definition is prior to
706    /// the definition of current module.
707    /// And also, `macro_use` on a module will import all legacy macros visible inside to
708    /// current legacy scope, with possible shadowing.
709    fn define_legacy_macro(&mut self, module_id: ModuleId, name: Name, mac: MacroId) {
710        // Always shadowing
711        self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
712    }
713
714    /// Define a macro 2.0 macro
715    ///
716    /// The scoped of macro 2.0 macro is equal to normal function
717    fn define_macro_def(
718        &mut self,
719        module_id: ModuleId,
720        name: Name,
721        macro_: Macro2Id,
722        vis: &RawVisibility,
723    ) {
724        let vis = self
725            .def_map
726            .resolve_visibility(
727                self.crate_local_def_map.unwrap_or(&self.local_def_map),
728                self.db,
729                module_id,
730                vis,
731                false,
732            )
733            .unwrap_or(Visibility::Public);
734        self.def_map.modules[module_id].scope.declare(macro_.into());
735        self.update(
736            module_id,
737            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
738            vis,
739            None,
740        );
741    }
742
743    /// Define a proc macro
744    ///
745    /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
746    /// And unconditionally exported.
747    fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
748        let module_id = self.def_map.root;
749        self.def_map.modules[module_id].scope.declare(macro_.into());
750        self.update(
751            module_id,
752            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
753            Visibility::Public,
754            None,
755        );
756    }
757
758    /// Import exported macros from another crate. `names`, if `Some(_)`, specifies the name of
759    /// macros to be imported. Otherwise this method imports all exported macros.
760    ///
761    /// Exported macros are just all macros in the root module scope.
762    /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
763    /// created by `use` in the root module, ignoring the visibility of `use`.
764    fn import_macros_from_extern_crate(
765        &mut self,
766        krate: Crate,
767        names: Option<Vec<Name>>,
768        extern_crate: Option<ExternCrateId>,
769    ) {
770        let def_map = crate_def_map(self.db, krate);
771        // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!`
772        // macros.
773        let root_scope = &def_map[def_map.root].scope;
774        match names {
775            Some(names) => {
776                for name in names {
777                    // FIXME: Report diagnostic on 404.
778                    if let Some(def) = root_scope.get(&name).take_macros() {
779                        self.def_map.macro_use_prelude.insert(name, (def, extern_crate));
780                    }
781                }
782            }
783            None => {
784                for (name, it) in root_scope.macros() {
785                    self.def_map.macro_use_prelude.insert(name.clone(), (it.def, extern_crate));
786                }
787            }
788        }
789    }
790
791    /// Tries to resolve every currently unresolved import.
792    fn resolve_imports(&mut self) -> ReachedFixedPoint {
793        let mut res = ReachedFixedPoint::Yes;
794        let imports = mem::take(&mut self.unresolved_imports);
795
796        self.unresolved_imports = imports
797            .into_iter()
798            .filter_map(|mut directive| {
799                directive.status = self.resolve_import(directive.module_id, &directive.import);
800                match directive.status {
801                    PartialResolvedImport::Indeterminate(resolved) => {
802                        self.record_resolved_import(&directive);
803                        self.indeterminate_imports.push((directive, resolved));
804                        res = ReachedFixedPoint::No;
805                        None
806                    }
807                    PartialResolvedImport::Resolved(_) => {
808                        self.record_resolved_import(&directive);
809                        res = ReachedFixedPoint::No;
810                        None
811                    }
812                    PartialResolvedImport::Unresolved => Some(directive),
813                }
814            })
815            .collect();
816
817        // Resolve all indeterminate resolved imports again
818        // As some of the macros will expand newly import shadowing partial resolved imports
819        // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
820        // correctly
821        let mut indeterminate_imports = std::mem::take(&mut self.indeterminate_imports);
822        indeterminate_imports.retain_mut(|(directive, partially_resolved)| {
823            let partially_resolved = partially_resolved.availability();
824            directive.status = self.resolve_import(directive.module_id, &directive.import);
825            match directive.status {
826                PartialResolvedImport::Indeterminate(import)
827                    if partially_resolved != import.availability() =>
828                {
829                    self.record_resolved_import(directive);
830                    res = ReachedFixedPoint::No;
831                    false
832                }
833                PartialResolvedImport::Resolved(_) => {
834                    self.record_resolved_import(directive);
835                    res = ReachedFixedPoint::No;
836                    false
837                }
838                _ => true,
839            }
840        });
841        self.indeterminate_imports = indeterminate_imports;
842
843        res
844    }
845
846    fn resolve_import(&self, module_id: ModuleId, import: &Import) -> PartialResolvedImport {
847        let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db, Edition::LATEST))
848            .entered();
849        tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
850        let ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info } =
851            self.def_map.resolve_path_fp_with_macro(
852                self.crate_local_def_map.unwrap_or(&self.local_def_map),
853                self.db,
854                ResolveMode::Import,
855                module_id,
856                &import.path,
857                BuiltinShadowMode::Module,
858                None, // An import may resolve to any kind of macro.
859            );
860
861        if reached_fixedpoint == ReachedFixedPoint::No
862            || resolved_def.is_none()
863            || segment_index.is_some()
864        {
865            return PartialResolvedImport::Unresolved;
866        }
867
868        if prefix_info.differing_crate {
869            return PartialResolvedImport::Resolved(
870                resolved_def.filter_visibility(|v| matches!(v, Visibility::Public)),
871            );
872        }
873
874        // Check whether all namespaces are resolved.
875        if resolved_def.is_full() {
876            PartialResolvedImport::Resolved(resolved_def)
877        } else {
878            PartialResolvedImport::Indeterminate(resolved_def)
879        }
880    }
881
882    fn record_resolved_import(&mut self, directive: &ImportDirective) {
883        let _p = tracing::info_span!("record_resolved_import").entered();
884
885        let module_id = directive.module_id;
886        let import = &directive.import;
887        let mut def = directive.status.namespaces();
888        let vis = self
889            .def_map
890            .resolve_visibility(
891                self.crate_local_def_map.unwrap_or(&self.local_def_map),
892                self.db,
893                module_id,
894                &directive.import.visibility,
895                false,
896            )
897            .unwrap_or(Visibility::Public);
898
899        match import.source {
900            ImportSource {
901                kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly),
902                id,
903                use_tree,
904                ..
905            } => {
906                let name = match &import.alias {
907                    Some(ImportAlias::Alias(name)) => Some(name),
908                    Some(ImportAlias::Underscore) => None,
909                    None => match import.path.segments().last() {
910                        Some(last_segment) => Some(last_segment),
911                        None => {
912                            cov_mark::hit!(bogus_paths);
913                            return;
914                        }
915                    },
916                };
917
918                if kind == ImportKind::TypeOnly {
919                    def.values = None;
920                    def.macros = None;
921                }
922                let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
923                tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
924
925                // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
926                // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
927                // or `pub use ::crate_name`.
928                //
929                // This has been historically allowed, but may be not allowed in future
930                // https://github.com/rust-lang/rust/issues/127909
931                if let Some(def) = def.types.as_mut() {
932                    let is_extern_crate_reimport_without_prefix = || {
933                        let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
934                            return false;
935                        };
936                        if kind == ImportKind::Glob {
937                            return false;
938                        }
939                        matches!(import.path.kind, PathKind::Plain | PathKind::SELF)
940                            && import.path.segments().len() < 2
941                    };
942                    if is_extern_crate_reimport_without_prefix() {
943                        def.vis = vis;
944                    }
945                }
946
947                self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
948            }
949            ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree, .. } => {
950                tracing::debug!("glob import: {:?}", import);
951                let glob = GlobId { use_: id, idx: use_tree };
952                match def.take_types() {
953                    Some(ModuleDefId::ModuleId(m)) => {
954                        if is_prelude {
955                            // Note: This dodgily overrides the injected prelude. The rustc
956                            // implementation seems to work the same though.
957                            cov_mark::hit!(std_prelude);
958                            self.def_map.prelude = Some((m, Some(id)));
959                        } else if m.krate(self.db) != self.def_map.krate {
960                            cov_mark::hit!(glob_across_crates);
961                            // glob import from other crate => we can just import everything once
962                            let scope = &m.def_map(self.db)[m].scope;
963
964                            // Module scoped macros is included
965                            let items = scope
966                                .resolutions()
967                                // only keep visible names...
968                                .map(|(n, res)| {
969                                    (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
970                                })
971                                .filter(|(_, res)| !res.is_none())
972                                .collect::<Vec<_>>();
973
974                            self.update(
975                                module_id,
976                                &items,
977                                vis,
978                                Some(ImportOrExternCrate::Glob(glob)),
979                            );
980                        } else {
981                            // glob import from same crate => we do an initial
982                            // import, and then need to propagate any further
983                            // additions
984                            let scope = if m.block(self.db) == self.def_map.block_id() {
985                                &self.def_map[m].scope
986                            } else {
987                                &m.def_map(self.db)[m].scope
988                            };
989
990                            // Module scoped macros is included
991                            let items = scope
992                                .resolutions()
993                                // only keep visible names...
994                                .map(|(n, res)| {
995                                    (
996                                        n,
997                                        res.filter_visibility(|v| {
998                                            v.is_visible_from_def_map(
999                                                self.db,
1000                                                &self.def_map,
1001                                                module_id,
1002                                            )
1003                                        }),
1004                                    )
1005                                })
1006                                .filter(|(_, res)| !res.is_none())
1007                                .collect::<Vec<_>>();
1008
1009                            self.update(
1010                                module_id,
1011                                &items,
1012                                vis,
1013                                Some(ImportOrExternCrate::Glob(glob)),
1014                            );
1015                            // record the glob import in case we add further items
1016                            let glob_imports = self.glob_imports.entry(m).or_default();
1017                            match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
1018                                None => glob_imports.push((module_id, vis, glob)),
1019                                Some((_, old_vis, _)) => {
1020                                    if let Some(new_vis) = old_vis.max(self.db, vis, &self.def_map)
1021                                    {
1022                                        *old_vis = new_vis;
1023                                    }
1024                                }
1025                            }
1026                        }
1027                    }
1028                    Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
1029                        cov_mark::hit!(glob_enum);
1030                        // glob import from enum => just import all the variants
1031                        let resolutions = e
1032                            .enum_variants(self.db)
1033                            .variants
1034                            .iter()
1035                            .map(|(name, &(variant, shape))| {
1036                                // We don't need to reduce the visibility, since enum variants and their fields do not have visibility on their own.
1037                                let res = if shape.has_value_ns_ctor() {
1038                                    PerNs::both(variant.into(), variant.into(), vis, None)
1039                                } else {
1040                                    PerNs::types(variant.into(), vis, None)
1041                                };
1042                                (Some(name.clone()), res)
1043                            })
1044                            .collect::<Vec<_>>();
1045                        self.update(
1046                            module_id,
1047                            &resolutions,
1048                            vis,
1049                            Some(ImportOrExternCrate::Glob(glob)),
1050                        );
1051                    }
1052                    Some(ModuleDefId::TraitId(it)) => {
1053                        // FIXME: Implement this correctly
1054                        // We can't actually call `trait_items`, the reason being that if macro calls
1055                        // occur, they will call back into the def map which we might be computing right
1056                        // now resulting in a cycle.
1057                        // To properly implement this, trait item collection needs to be done in def map
1058                        // collection...
1059                        let resolutions = if true {
1060                            vec![]
1061                        } else {
1062                            TraitItems::query(self.db, it)
1063                                .items
1064                                .iter()
1065                                .map(|&(ref name, variant)| {
1066                                    let res = match variant {
1067                                        AssocItemId::FunctionId(it) => {
1068                                            PerNs::values(it.into(), vis, None)
1069                                        }
1070                                        AssocItemId::ConstId(it) => {
1071                                            PerNs::values(it.into(), vis, None)
1072                                        }
1073                                        AssocItemId::TypeAliasId(it) => {
1074                                            PerNs::types(it.into(), vis, None)
1075                                        }
1076                                    };
1077                                    (Some(name.clone()), res)
1078                                })
1079                                .collect::<Vec<_>>()
1080                        };
1081                        self.update(
1082                            module_id,
1083                            &resolutions,
1084                            vis,
1085                            Some(ImportOrExternCrate::Glob(glob)),
1086                        );
1087                    }
1088                    Some(d) => {
1089                        tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
1090                    }
1091                    None => {
1092                        tracing::debug!("glob import {:?} didn't resolve as type", import);
1093                    }
1094                }
1095            }
1096        }
1097    }
1098
1099    fn update(
1100        &mut self,
1101        // The module for which `resolutions` have been resolve
1102        module_id: ModuleId,
1103        resolutions: &[(Option<Name>, PerNs)],
1104        // Visibility this import will have
1105        vis: Visibility,
1106        import: Option<ImportOrExternCrate>,
1107    ) {
1108        self.update_recursive(module_id, resolutions, vis, import, 0)
1109    }
1110
1111    fn update_recursive(
1112        &mut self,
1113        // The module for which `resolutions` have been resolved.
1114        module_id: ModuleId,
1115        resolutions: &[(Option<Name>, PerNs)],
1116        // All resolutions are imported with this visibility; the visibilities in
1117        // the `PerNs` values are ignored and overwritten
1118        vis: Visibility,
1119        import: Option<ImportOrExternCrate>,
1120        depth: usize,
1121    ) {
1122        if depth > GLOB_RECURSION_LIMIT {
1123            // prevent stack overflows (but this shouldn't be possible)
1124            panic!("infinite recursion in glob imports!");
1125        }
1126        let mut changed = false;
1127
1128        for (name, res) in resolutions {
1129            match name {
1130                Some(name) => {
1131                    changed |=
1132                        self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
1133                }
1134                None => {
1135                    let (tr, import) = match res.take_types_full() {
1136                        Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
1137                            (tr, import)
1138                        }
1139                        Some(other) => {
1140                            tracing::debug!("non-trait `_` import of {:?}", other);
1141                            continue;
1142                        }
1143                        None => continue,
1144                    };
1145                    let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
1146                    let should_update = match old_vis {
1147                        None => true,
1148                        Some(old_vis) => {
1149                            let max_vis = old_vis.max(self.db, vis, &self.def_map).unwrap_or_else(|| {
1150                                panic!("`Tr as _` imports with unrelated visibilities {old_vis:?} and {vis:?} (trait {tr:?})");
1151                            });
1152
1153                            if max_vis == old_vis {
1154                                false
1155                            } else {
1156                                cov_mark::hit!(upgrade_underscore_visibility);
1157                                true
1158                            }
1159                        }
1160                    };
1161
1162                    if should_update {
1163                        changed = true;
1164                        self.def_map.modules[module_id].scope.push_unnamed_trait(
1165                            tr,
1166                            vis,
1167                            import.and_then(ImportOrExternCrate::import),
1168                        );
1169                    }
1170                }
1171            }
1172        }
1173
1174        if !changed {
1175            return;
1176        }
1177        let glob_imports = self
1178            .glob_imports
1179            .get(&module_id)
1180            .into_iter()
1181            .flatten()
1182            .filter(|(glob_importing_module, _, _)| {
1183                // we know all resolutions have the same visibility (`vis`), so we
1184                // just need to check that once
1185                vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
1186            })
1187            .cloned()
1188            .collect::<Vec<_>>();
1189
1190        for (glob_importing_module, glob_import_vis, glob) in glob_imports {
1191            let vis = glob_import_vis.min(self.db, vis, &self.def_map).unwrap_or(glob_import_vis);
1192            self.update_recursive(
1193                glob_importing_module,
1194                resolutions,
1195                vis,
1196                Some(ImportOrExternCrate::Glob(glob)),
1197                depth + 1,
1198            );
1199        }
1200    }
1201
1202    fn push_res_and_update_glob_vis(
1203        &mut self,
1204        module_id: ModuleId,
1205        name: &Name,
1206        mut defs: PerNs,
1207        vis: Visibility,
1208        def_import_type: Option<ImportOrExternCrate>,
1209    ) -> bool {
1210        if let Some(def) = defs.types.as_mut() {
1211            def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1212        }
1213        if let Some(def) = defs.values.as_mut() {
1214            def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1215        }
1216        if let Some(def) = defs.macros.as_mut() {
1217            def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1218        }
1219
1220        let mut changed = false;
1221
1222        if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
1223            let prev_defs = self.def_map[module_id].scope.get(name);
1224
1225            // Multiple globs may import the same item and they may override visibility from
1226            // previously resolved globs. Handle overrides here and leave the rest to
1227            // `ItemScope::push_res_with_import()`.
1228            if let Some(def) = defs.types
1229                && let Some(prev_def) = prev_defs.types
1230            {
1231                if def.def == prev_def.def
1232                    && self.from_glob_import.contains_type(module_id, name.clone())
1233                    && def.vis != prev_def.vis
1234                    && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1235                {
1236                    changed = true;
1237                    // This import is being handled here, don't pass it down to
1238                    // `ItemScope::push_res_with_import()`.
1239                    defs.types = None;
1240                    self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
1241                }
1242                // When the source module's definition changed (e.g., due to an explicit import
1243                // shadowing a glob), propagate the new definition to modules that glob-import from it.
1244                // We check that the previous definition came from the same glob import to avoid
1245                // incorrectly overwriting definitions from different glob sources.
1246                //
1247                // Note this is not a perfect fix, but it makes
1248                // https://github.com/rust-lang/rust-analyzer/issues/19224 work for now until we
1249                // implement a proper glob graph
1250                else if def.def != prev_def.def && prev_def.import == def_import_type {
1251                    changed = true;
1252                    defs.types = None;
1253                    self.def_map.modules[module_id].scope.update_def_types(name, def.def, def.vis);
1254                }
1255            }
1256
1257            if let Some(def) = defs.values
1258                && let Some(prev_def) = prev_defs.values
1259            {
1260                if def.def == prev_def.def
1261                    && self.from_glob_import.contains_value(module_id, name.clone())
1262                    && def.vis != prev_def.vis
1263                    && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1264                {
1265                    changed = true;
1266                    defs.values = None;
1267                    self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
1268                } else if def.def != prev_def.def
1269                    && prev_def.import.map(ImportOrExternCrate::from) == def_import_type
1270                {
1271                    changed = true;
1272                    defs.values = None;
1273                    self.def_map.modules[module_id].scope.update_def_values(name, def.def, def.vis);
1274                }
1275            }
1276
1277            if let Some(def) = defs.macros
1278                && let Some(prev_def) = prev_defs.macros
1279            {
1280                if def.def == prev_def.def
1281                    && self.from_glob_import.contains_macro(module_id, name.clone())
1282                    && def.vis != prev_def.vis
1283                    && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1284                {
1285                    changed = true;
1286                    defs.macros = None;
1287                    self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
1288                } else if def.def != prev_def.def && prev_def.import == def_import_type {
1289                    changed = true;
1290                    defs.macros = None;
1291                    self.def_map.modules[module_id].scope.update_def_macros(name, def.def, def.vis);
1292                }
1293            }
1294        }
1295
1296        changed |= self.def_map.modules[module_id].scope.push_res_with_import(
1297            &mut self.from_glob_import,
1298            (module_id, name.clone()),
1299            defs,
1300            def_import_type,
1301        );
1302
1303        changed
1304    }
1305
1306    fn resolve_macros(&mut self) -> ReachedFixedPoint {
1307        let mut macros = mem::take(&mut self.unresolved_macros);
1308        let mut resolved = Vec::new();
1309        let push_resolved = |resolved: &mut Vec<_>, directive: &MacroDirective<'_>, call_id| {
1310            let attr_macro_item = match &directive.kind {
1311                MacroDirectiveKind::Attr { ast_id, .. } => Some(ast_id.ast_id),
1312                MacroDirectiveKind::FnLike { .. } | MacroDirectiveKind::Derive { .. } => None,
1313            };
1314            resolved.push((
1315                directive.module_id,
1316                directive.depth,
1317                directive.container,
1318                call_id,
1319                attr_macro_item,
1320            ));
1321        };
1322
1323        #[derive(PartialEq, Eq)]
1324        enum Resolved {
1325            Yes,
1326            No,
1327        }
1328
1329        let mut eager_callback_buffer = vec![];
1330        let mut res = ReachedFixedPoint::Yes;
1331        // Retain unresolved macros after this round of resolution.
1332        let mut retain = |directive: &MacroDirective<'db>| {
1333            let subns = match &directive.kind {
1334                MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
1335                MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
1336                    MacroSubNs::Attr
1337                }
1338            };
1339            let resolver = |def_map: &DefMap, path: &_| {
1340                let resolved_res = def_map.resolve_path_fp_with_macro(
1341                    self.crate_local_def_map.unwrap_or(&self.local_def_map),
1342                    self.db,
1343                    ResolveMode::Other,
1344                    directive.module_id,
1345                    path,
1346                    BuiltinShadowMode::Module,
1347                    Some(subns),
1348                );
1349                resolved_res.resolved_def.take_macros().map(|it| (it, it.definition(self.db)))
1350            };
1351            let resolver_def_id = |path: &_| resolver(&self.def_map, path).map(|(_, it)| it);
1352
1353            match &directive.kind {
1354                MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1355                    let call_id = macro_call_as_call_id(
1356                        self.db,
1357                        ast_id.ast_id,
1358                        &ast_id.path,
1359                        *call_site,
1360                        *expand_to,
1361                        self.def_map.krate,
1362                        directive.depth,
1363                        self.def_map.recursion_limit(),
1364                        resolver_def_id,
1365                        &mut |ptr, call_id| {
1366                            eager_callback_buffer.push((directive.module_id, ptr, call_id));
1367                        },
1368                    );
1369                    if let Ok(call_id) = call_id {
1370                        // FIXME: Expansion error
1371                        if let Some(call_id) = call_id.value {
1372                            self.def_map.modules[directive.module_id]
1373                                .scope
1374                                .add_macro_invoc(ast_id.ast_id, call_id);
1375
1376                            push_resolved(&mut resolved, directive, call_id);
1377
1378                            res = ReachedFixedPoint::No;
1379                            return Resolved::Yes;
1380                        }
1381                    }
1382                }
1383                MacroDirectiveKind::Derive {
1384                    ast_id,
1385                    derive_attr,
1386                    derive_pos,
1387                    ctxt: call_site,
1388                    derive_macro_id,
1389                } => {
1390                    // FIXME: This code is almost duplicate below.
1391                    let id = derive_macro_as_call_id(
1392                        self.db,
1393                        ast_id,
1394                        *derive_attr,
1395                        *derive_pos as u32,
1396                        *call_site,
1397                        self.def_map.krate,
1398                        |path| resolver(&self.def_map, path),
1399                        *derive_macro_id,
1400                        directive.depth,
1401                    );
1402
1403                    if let Ok((macro_id, def_id, call_id)) = id {
1404                        self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1405                            ast_id.ast_id,
1406                            Either::Left(call_id),
1407                            *derive_attr,
1408                            *derive_pos,
1409                        );
1410                        // Record its helper attributes.
1411                        if def_id.krate != self.def_map.krate {
1412                            let def_map = crate_def_map(self.db, def_id.krate);
1413                            if let Some(helpers) = def_map.data.exported_derives.get(&macro_id) {
1414                                self.def_map
1415                                    .derive_helpers_in_scope
1416                                    .entry(ast_id.ast_id.map(|it| it.upcast()))
1417                                    .or_default()
1418                                    .extend(izip!(
1419                                        helpers.iter().cloned(),
1420                                        iter::repeat(macro_id),
1421                                        iter::repeat(Either::Left(call_id)),
1422                                    ));
1423                            }
1424                        }
1425
1426                        push_resolved(&mut resolved, directive, call_id);
1427
1428                        res = ReachedFixedPoint::No;
1429                        return Resolved::Yes;
1430                    }
1431                }
1432                MacroDirectiveKind::Attr {
1433                    ast_id: file_ast_id,
1434                    mod_item,
1435                    attr_id,
1436                    attr,
1437                    tree,
1438                    item_tree,
1439                } => {
1440                    let &AstIdWithPath { ast_id, ref path } = file_ast_id;
1441                    let file_id = ast_id.file_id;
1442
1443                    let mut recollect_without = |collector: &mut Self| {
1444                        // Remove the original directive since we resolved it.
1445                        let mod_dir = collector.mod_dirs[&directive.module_id].clone();
1446                        collector.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr_id);
1447
1448                        ModCollector {
1449                            def_collector: collector,
1450                            macro_depth: directive.depth,
1451                            module_id: directive.module_id,
1452                            tree_id: *tree,
1453                            item_tree,
1454                            mod_dir,
1455                        }
1456                        .collect(&[*mod_item], directive.container);
1457                        res = ReachedFixedPoint::No;
1458                        Resolved::Yes
1459                    };
1460
1461                    if let Some(ident) = path.as_ident()
1462                        && let Some(helpers) = self.def_map.derive_helpers_in_scope.get(&ast_id)
1463                        && helpers.iter().any(|(it, ..)| it == ident)
1464                    {
1465                        cov_mark::hit!(resolved_derive_helper);
1466                        // Resolved to derive helper. Collect the item's attributes again,
1467                        // starting after the derive helper.
1468                        return recollect_without(self);
1469                    }
1470
1471                    let def = match resolver_def_id(path) {
1472                        Some(def) if def.is_attribute() => def,
1473                        _ => return Resolved::No,
1474                    };
1475
1476                    // Skip #[test]/#[bench]/#[test_case] expansion, which would merely result in more memory usage
1477                    // due to duplicating functions into macro expansions, but only if `cfg(test)` is active,
1478                    // otherwise they are expanded to nothing and this can impact e.g. diagnostics (due to things
1479                    // being cfg'ed out).
1480                    // Ideally we will just expand them to nothing here. But we are only collecting macro calls,
1481                    // not expanding them, so we have no way to do that.
1482                    if matches!(
1483                        def.kind,
1484                        MacroDefKind::BuiltInAttr(_, expander)
1485                        if expander.is_test() || expander.is_bench() || expander.is_test_case()
1486                    ) {
1487                        let test_is_active = self.cfg_options.check_atom(&CfgAtom::Flag(sym::test));
1488                        if test_is_active {
1489                            return recollect_without(self);
1490                        }
1491                    }
1492
1493                    let mut call_id = || {
1494                        let active_attrs = self.prev_active_attrs.entry(ast_id).or_default();
1495                        active_attrs.push(*attr_id);
1496
1497                        attr_macro_as_call_id(
1498                            self.db,
1499                            file_ast_id,
1500                            attr,
1501                            AttrMacroAttrIds::from_many(active_attrs),
1502                            self.def_map.krate,
1503                            def,
1504                            directive.depth,
1505                        )
1506                    };
1507                    if matches!(def,
1508                        MacroDefId { kind: MacroDefKind::BuiltInAttr(_, exp), .. }
1509                        if exp.is_derive()
1510                    ) {
1511                        // Resolved to `#[derive]`, we don't actually expand this attribute like
1512                        // normal (as that would just be an identity expansion with extra output)
1513                        // Instead we treat derive attributes special and apply them separately.
1514
1515                        let ast_adt_id: FileAstId<ast::Adt> = match item_tree.index(*mod_item) {
1516                            ModItemKind::Struct(ast_id, _) => ast_id.upcast(),
1517                            ModItemKind::Union(ast_id, _) => ast_id.upcast(),
1518                            ModItemKind::Enum(ast_id, _) => ast_id.upcast(),
1519                            _ => {
1520                                let diag = DefDiagnostic::invalid_derive_target(
1521                                    directive.module_id,
1522                                    ast_id,
1523                                    *attr_id,
1524                                );
1525                                self.def_map.diagnostics.push(diag);
1526                                return recollect_without(self);
1527                            }
1528                        };
1529
1530                        let ast_id = ast_id.with_value(ast_adt_id);
1531
1532                        let mut derive_call_ids = SmallVec::new();
1533                        match attr.parse_path_comma_token_tree(self.db) {
1534                            Some(derive_macros) => {
1535                                let call_id = call_id();
1536                                for (idx, (path, call_site, _)) in derive_macros.enumerate() {
1537                                    let ast_id = AstIdWithPath::new(
1538                                        file_id,
1539                                        ast_id.value,
1540                                        Interned::new(path),
1541                                    );
1542
1543                                    derive_call_ids.push(None);
1544
1545                                    // Try to resolve the derive immediately. If we succeed, we can also use the fast path
1546                                    // for builtin derives. If not, we cannot use it, as it can cause the ADT to become
1547                                    // interned while the derive is still unresolved, which will cause it to get forgotten.
1548                                    let id = derive_macro_as_call_id(
1549                                        self.db,
1550                                        &ast_id,
1551                                        *attr_id,
1552                                        idx as u32,
1553                                        call_site.ctx,
1554                                        self.def_map.krate,
1555                                        |path| resolver(&self.def_map, path),
1556                                        call_id,
1557                                        directive.depth,
1558                                    );
1559
1560                                    let ast_id_without_path = ast_id.ast_id;
1561                                    let directive = MacroDirective {
1562                                        module_id: directive.module_id,
1563                                        depth: directive.depth + 1,
1564                                        kind: MacroDirectiveKind::Derive {
1565                                            ast_id,
1566                                            derive_attr: *attr_id,
1567                                            derive_pos: idx,
1568                                            ctxt: call_site.ctx,
1569                                            derive_macro_id: call_id,
1570                                        },
1571                                        container: directive.container,
1572                                    };
1573
1574                                    if let Ok((macro_id, def_id, call_id)) = id {
1575                                        let (mut helpers_start, mut helpers_end) = (0, 0);
1576                                        // Record its helper attributes.
1577                                        if def_id.krate != self.def_map.krate {
1578                                            let def_map = crate_def_map(self.db, def_id.krate);
1579                                            if let Some(helpers) =
1580                                                def_map.data.exported_derives.get(&macro_id)
1581                                            {
1582                                                let derive_helpers = self
1583                                                    .def_map
1584                                                    .derive_helpers_in_scope
1585                                                    .entry(
1586                                                        ast_id_without_path.map(|it| it.upcast()),
1587                                                    )
1588                                                    .or_default();
1589                                                helpers_start = derive_helpers.len();
1590                                                derive_helpers.extend(izip!(
1591                                                    helpers.iter().cloned(),
1592                                                    iter::repeat(macro_id),
1593                                                    iter::repeat(Either::Left(call_id)),
1594                                                ));
1595                                                helpers_end = derive_helpers.len();
1596                                            }
1597                                        }
1598
1599                                        if super::enable_builtin_derive_fast_path()
1600                                            && let MacroDefKind::BuiltInDerive(_, builtin_derive) =
1601                                                def_id.kind
1602                                            && crate::builtin_derive::has_builtin_derive_impl(
1603                                                builtin_derive,
1604                                            )
1605                                        {
1606                                            self.deferred_builtin_derives
1607                                                .entry(ast_id_without_path.upcast())
1608                                                .or_default()
1609                                                .push(DeferredBuiltinDerive {
1610                                                    call_id,
1611                                                    derive: builtin_derive,
1612                                                    module_id: directive.module_id,
1613                                                    container: directive.container,
1614                                                    depth: directive.depth,
1615                                                    derive_attr_id: *attr_id,
1616                                                    derive_index: idx as u32,
1617                                                    helpers_range: helpers_start..helpers_end,
1618                                                });
1619                                        } else {
1620                                            push_resolved(&mut resolved, &directive, call_id);
1621                                            *derive_call_ids.last_mut().unwrap() =
1622                                                Some(Either::Left(call_id));
1623                                        }
1624                                    } else {
1625                                        self.unresolved_macros.push(directive);
1626                                    }
1627                                }
1628
1629                                // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection.
1630                                // This is just a trick to be able to resolve the input to derives
1631                                // as proper paths in `Semantics`.
1632                                // Check the comment in [`builtin_attr_macro`].
1633                                self.def_map.modules[directive.module_id]
1634                                    .scope
1635                                    .init_derive_attribute(
1636                                        ast_id,
1637                                        *attr_id,
1638                                        call_id,
1639                                        derive_call_ids,
1640                                    );
1641                            }
1642                            None => {
1643                                let diag = DefDiagnostic::malformed_derive(
1644                                    directive.module_id,
1645                                    ast_id,
1646                                    *attr_id,
1647                                );
1648                                self.def_map.diagnostics.push(diag);
1649                            }
1650                        }
1651
1652                        return recollect_without(self);
1653                    }
1654
1655                    if let MacroDefKind::ProcMacro(_, exp, _) = def.kind {
1656                        // If there's no expander for the proc macro (e.g.
1657                        // because proc macros are disabled, or building the
1658                        // proc macro crate failed), report this and skip
1659                        // expansion like we would if it was disabled
1660                        if let Some(err) = exp.as_expand_error(def.krate) {
1661                            self.def_map.diagnostics.push(DefDiagnostic::macro_error(
1662                                directive.module_id,
1663                                ast_id,
1664                                (**path).clone(),
1665                                err,
1666                            ));
1667                            return recollect_without(self);
1668                        }
1669                    }
1670
1671                    // Clear deferred derives for this item, unfortunately we cannot use them due to the attribute.
1672                    if let Some(deferred_derives) = self.deferred_builtin_derives.remove(&ast_id) {
1673                        resolved.extend(deferred_derives.into_iter().map(|derive| {
1674                            (
1675                                derive.module_id,
1676                                derive.depth,
1677                                derive.container,
1678                                derive.call_id,
1679                                Some(ast_id),
1680                            )
1681                        }));
1682                    }
1683
1684                    let call_id = call_id();
1685                    self.def_map.modules[directive.module_id]
1686                        .scope
1687                        .add_attr_macro_invoc(ast_id, call_id);
1688
1689                    push_resolved(&mut resolved, directive, call_id);
1690                    res = ReachedFixedPoint::No;
1691                    return Resolved::Yes;
1692                }
1693            }
1694
1695            Resolved::No
1696        };
1697        macros.retain(|it| retain(it) == Resolved::No);
1698        // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1699        macros.extend(mem::take(&mut self.unresolved_macros));
1700        self.unresolved_macros = macros;
1701
1702        for (module_id, ptr, call_id) in eager_callback_buffer {
1703            self.def_map.modules[module_id].scope.add_macro_invoc(ptr.map(|(_, it)| it), call_id);
1704        }
1705
1706        for (module_id, depth, container, macro_call_id, attr_macro_item) in resolved {
1707            self.collect_macro_expansion(
1708                module_id,
1709                macro_call_id,
1710                depth,
1711                container,
1712                attr_macro_item,
1713            );
1714        }
1715
1716        res
1717    }
1718
1719    fn collect_macro_expansion(
1720        &mut self,
1721        module_id: ModuleId,
1722        macro_call_id: MacroCallId,
1723        depth: u32,
1724        container: ItemContainerId,
1725        attr_macro_item: Option<AstId<ast::Item>>,
1726    ) {
1727        if depth > self.def_map.recursion_limit() {
1728            cov_mark::hit!(macro_expansion_overflow);
1729            tracing::warn!("macro expansion is too deep");
1730            return;
1731        }
1732        let file_id = macro_call_id.into();
1733
1734        let item_tree = file_item_tree(self.db, file_id, self.def_map.krate);
1735
1736        // Derive helpers that are in scope for an item are also in scope for attribute macro expansions
1737        // of that item (but not derive or fn like macros).
1738        // FIXME: This is a hack. The proper way to do this is by having a chain of derive helpers scope,
1739        // where the next scope in the chain is the parent hygiene context of the span. Unfortunately
1740        // it's difficult to implement with our current name resolution and hygiene system.
1741        // This hack is also incorrect since it ignores item in blocks. But the main reason to bring derive
1742        // helpers into scope in this case is to help with:
1743        // ```
1744        // #[derive(DeriveWithHelper)]
1745        // #[helper]
1746        // #[attr_macro]
1747        // struct Foo;
1748        // ```
1749        // Where `attr_macro`'s input will include `#[helper]` but not the derive, and it will likely therefore
1750        // also include it in its output. Therefore I hope not supporting blocks is fine at least for now.
1751        if let Some(attr_macro_item) = attr_macro_item
1752            && let Some(derive_helpers) = self.def_map.derive_helpers_in_scope.get(&attr_macro_item)
1753        {
1754            let derive_helpers = derive_helpers.clone();
1755            for item in item_tree.top_level_items() {
1756                self.def_map
1757                    .derive_helpers_in_scope
1758                    .entry(InFile::new(file_id, item.ast_id(item_tree)))
1759                    .or_default()
1760                    .extend(derive_helpers.iter().cloned());
1761            }
1762        }
1763
1764        let mod_dir = if macro_call_id.is_include_macro(self.db) {
1765            ModDir::root()
1766        } else {
1767            self.mod_dirs[&module_id].clone()
1768        };
1769
1770        ModCollector {
1771            def_collector: &mut *self,
1772            macro_depth: depth,
1773            tree_id: TreeId::new(file_id, None),
1774            module_id,
1775            item_tree,
1776            mod_dir,
1777        }
1778        .collect(item_tree.top_level_items(), container);
1779    }
1780
1781    fn finish(mut self) -> (DefMap, LocalDefMap) {
1782        // Emit diagnostics for all remaining unexpanded macros.
1783        let _p = tracing::info_span!("DefCollector::finish").entered();
1784
1785        for directive in &self.unresolved_macros {
1786            match &directive.kind {
1787                MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1788                    // FIXME: we shouldn't need to re-resolve the macro here just to get the unresolved error!
1789                    let macro_call_as_call_id = macro_call_as_call_id(
1790                        self.db,
1791                        ast_id.ast_id,
1792                        &ast_id.path,
1793                        *call_site,
1794                        *expand_to,
1795                        self.def_map.krate,
1796                        directive.depth,
1797                        self.def_map.recursion_limit(),
1798                        |path| {
1799                            let resolved_res = self.def_map.resolve_path_fp_with_macro(
1800                                self.crate_local_def_map.unwrap_or(&self.local_def_map),
1801                                self.db,
1802                                ResolveMode::Other,
1803                                directive.module_id,
1804                                path,
1805                                BuiltinShadowMode::Module,
1806                                Some(MacroSubNs::Bang),
1807                            );
1808                            resolved_res.resolved_def.take_macros().map(|it| it.definition(self.db))
1809                        },
1810                        &mut |_, _| (),
1811                    );
1812                    if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
1813                        self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1814                            directive.module_id,
1815                            MacroCallKind::FnLike {
1816                                ast_id: ast_id.ast_id,
1817                                expand_to: *expand_to,
1818                                eager: None,
1819                            },
1820                            path,
1821                        ));
1822                    }
1823                }
1824                MacroDirectiveKind::Derive {
1825                    ast_id,
1826                    derive_attr,
1827                    derive_pos,
1828                    derive_macro_id,
1829                    ..
1830                } => {
1831                    self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1832                        directive.module_id,
1833                        MacroCallKind::Derive {
1834                            ast_id: ast_id.ast_id,
1835                            derive_attr_index: *derive_attr,
1836                            derive_index: *derive_pos as u32,
1837                            derive_macro_id: *derive_macro_id,
1838                        },
1839                        (*ast_id.path).clone(),
1840                    ));
1841                }
1842                // These are diagnosed by `reseed_with_unresolved_attribute`, as that function consumes them
1843                MacroDirectiveKind::Attr { .. } => {}
1844            }
1845        }
1846
1847        // Emit diagnostics for all remaining unresolved imports.
1848        for import in &self.unresolved_imports {
1849            let &ImportDirective {
1850                module_id,
1851                import:
1852                    Import {
1853                        ref path,
1854                        source: ImportSource { use_tree, id, is_prelude: _, kind: _ },
1855                        ..
1856                    },
1857                ..
1858            } = import;
1859            if matches!(
1860                (path.segments().first(), &path.kind),
1861                (Some(krate), PathKind::Plain | PathKind::Abs) if self.unresolved_extern_crates.contains(krate)
1862            ) {
1863                continue;
1864            }
1865            let item_tree_id = id.lookup(self.db).id;
1866            self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1867                module_id,
1868                item_tree_id,
1869                use_tree,
1870            ));
1871        }
1872
1873        always!(
1874            self.deferred_builtin_derives.is_empty(),
1875            "self.deferred_builtin_derives={:#?}",
1876            self.deferred_builtin_derives,
1877        );
1878
1879        (self.def_map, self.local_def_map)
1880    }
1881}
1882
1883/// Walks a single module, populating defs, imports and macros
1884struct ModCollector<'a, 'db> {
1885    def_collector: &'a mut DefCollector<'db>,
1886    macro_depth: u32,
1887    module_id: ModuleId,
1888    tree_id: TreeId,
1889    item_tree: &'db ItemTree,
1890    mod_dir: ModDir,
1891}
1892
1893impl ModCollector<'_, '_> {
1894    fn collect_in_top_module(&mut self, items: &[ModItemId]) {
1895        self.collect(items, self.module_id.into())
1896    }
1897
1898    fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) {
1899        let is_crate_root = self.module_id == self.def_collector.def_map.root
1900            && self.def_collector.def_map.block.is_none();
1901
1902        // Note: don't assert that inserted value is fresh: it's simply not true
1903        // for macros.
1904        self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1905
1906        let db = self.def_collector.db;
1907        let module_id = self.module_id;
1908        let consider_deferred_derives =
1909            |file_id: HirFileId,
1910             deferred_derives: &mut FxHashMap<_, Vec<DeferredBuiltinDerive>>,
1911             ast_id: FileAstId<ast::Adt>,
1912             id: AdtId,
1913             def_map: &mut DefMap| {
1914                let ast_id = InFile::new(file_id, ast_id.upcast());
1915                let Some(deferred_derives) = deferred_derives.remove(&ast_id.upcast()) else {
1916                    return;
1917                };
1918                let module = &mut def_map.modules[module_id];
1919                for deferred_derive in deferred_derives {
1920                    crate::builtin_derive::with_derive_traits(deferred_derive.derive, |trait_| {
1921                        let impl_id = BuiltinDeriveImplId::new(
1922                            db,
1923                            BuiltinDeriveImplLoc {
1924                                adt: id,
1925                                trait_,
1926                                derive_attr_id: deferred_derive.derive_attr_id,
1927                                derive_index: deferred_derive.derive_index,
1928                            },
1929                        );
1930                        module.scope.define_builtin_derive_impl(impl_id);
1931                        module.scope.set_derive_macro_invoc(
1932                            ast_id,
1933                            Either::Right(impl_id),
1934                            deferred_derive.derive_attr_id,
1935                            deferred_derive.derive_index as usize,
1936                        );
1937                        // Change its helper attributes to the new id.
1938                        if let Some(derive_helpers) =
1939                            def_map.derive_helpers_in_scope.get_mut(&ast_id.map(|it| it.upcast()))
1940                        {
1941                            for (_, _, call_id) in
1942                                &mut derive_helpers[deferred_derive.helpers_range.clone()]
1943                            {
1944                                *call_id = Either::Right(impl_id);
1945                            }
1946                        }
1947                    });
1948                }
1949            };
1950        let update_def =
1951            |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, value_ns_ctor_vis| {
1952                def_collector.def_map.modules[module_id].scope.declare(id);
1953                def_collector.update(
1954                    module_id,
1955                    &[(Some(name.clone()), PerNs::from_def(id, vis, value_ns_ctor_vis, None))],
1956                    vis,
1957                    None,
1958                )
1959            };
1960        let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| {
1961            def_map
1962                .resolve_visibility(local_def_map, db, module_id, visibility, false)
1963                .unwrap_or(Visibility::Public)
1964        };
1965
1966        let item_tree = self.item_tree;
1967
1968        let mut process_mod_item = |item_id: ModItemId| {
1969            let attrs = match self.item_tree.attrs(item_id) {
1970                Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
1971                None => Attrs::EMPTY,
1972                Some(AttrsOrCfg::CfgDisabled(cfg)) => {
1973                    let ast_id = item_id.ast_id(self.item_tree).erase();
1974                    self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg.0);
1975                    return;
1976                }
1977            };
1978
1979            if let Err(()) = self.resolve_attributes(attrs, item_id, container) {
1980                // Do not process the item. It has at least one non-builtin attribute, so the
1981                // fixed-point algorithm is required to resolve the rest of them.
1982                return;
1983            }
1984
1985            let def_map = &mut self.def_collector.def_map;
1986            let local_def_map =
1987                self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map);
1988
1989            match self.item_tree.index(item_id) {
1990                ModItemKind::Mod(ast_id, module) => self.collect_module(ast_id, module, attrs),
1991                ModItemKind::Use(ast_id, use_) => {
1992                    let id =
1993                        UseLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
1994                            .intern(db);
1995                    let is_prelude = attrs.by_key(sym::prelude_import).exists();
1996                    Import::from_use(self.item_tree, use_, id, is_prelude, |import| {
1997                        self.def_collector.unresolved_imports.push(ImportDirective {
1998                            module_id: self.module_id,
1999                            import,
2000                            status: PartialResolvedImport::Unresolved,
2001                        });
2002                    })
2003                }
2004                ModItemKind::ExternCrate(ast_id, item) => {
2005                    let item_tree::ExternCrate { name, visibility, alias } = item;
2006
2007                    let id = ExternCrateLoc {
2008                        container: module_id,
2009                        id: InFile::new(self.tree_id.file_id(), ast_id),
2010                    }
2011                    .intern(db);
2012                    def_map.modules[self.module_id].scope.define_extern_crate_decl(id);
2013
2014                    let is_self = *name == sym::self_;
2015                    let resolved = if is_self {
2016                        cov_mark::hit!(extern_crate_self_as);
2017                        Some(def_map.crate_root(db))
2018                    } else {
2019                        self.def_collector
2020                            .deps
2021                            .get(name)
2022                            .map(|dep| crate_def_map(db, dep.crate_id).root_module_id())
2023                    };
2024
2025                    let name = match alias {
2026                        Some(ImportAlias::Alias(name)) => Some(name),
2027                        Some(ImportAlias::Underscore) => None,
2028                        None => Some(name),
2029                    };
2030
2031                    if let Some(resolved) = resolved {
2032                        let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]);
2033
2034                        if is_crate_root {
2035                            // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
2036                            if let Some(name) = name {
2037                                self.def_collector
2038                                    .local_def_map
2039                                    .extern_prelude
2040                                    .insert(name.clone(), (resolved, Some(id)));
2041                            }
2042                            // they also allow `#[macro_use]`
2043                            if !is_self {
2044                                self.process_macro_use_extern_crate(
2045                                    id,
2046                                    attrs.by_key(sym::macro_use).attrs(),
2047                                    resolved.krate(self.def_collector.db),
2048                                );
2049                            }
2050                        }
2051
2052                        self.def_collector.update(
2053                            module_id,
2054                            &[(
2055                                name.cloned(),
2056                                PerNs::types(
2057                                    resolved.into(),
2058                                    vis,
2059                                    Some(ImportOrExternCrate::ExternCrate(id)),
2060                                ),
2061                            )],
2062                            vis,
2063                            Some(ImportOrExternCrate::ExternCrate(id)),
2064                        );
2065                    } else {
2066                        if let Some(name) = name {
2067                            self.def_collector.unresolved_extern_crates.insert(name.clone());
2068                        }
2069                        self.def_collector.def_map.diagnostics.push(
2070                            DefDiagnostic::unresolved_extern_crate(
2071                                module_id,
2072                                InFile::new(self.file_id(), ast_id),
2073                            ),
2074                        );
2075                    }
2076                }
2077                ModItemKind::ExternBlock(ast_id, block) => {
2078                    let extern_block_id = ExternBlockLoc {
2079                        container: module_id,
2080                        id: InFile::new(self.file_id(), ast_id),
2081                    }
2082                    .intern(db);
2083                    self.def_collector.def_map.modules[self.module_id]
2084                        .scope
2085                        .define_extern_block(extern_block_id);
2086                    self.collect(&block.children, ItemContainerId::ExternBlockId(extern_block_id))
2087                }
2088                ModItemKind::MacroCall(ast_id, mac) => {
2089                    self.collect_macro_call(ast_id, mac, container)
2090                }
2091                ModItemKind::MacroRules(ast_id, mac) => {
2092                    self.collect_macro_rules(attrs, ast_id, mac, module_id)
2093                }
2094                ModItemKind::Macro2(ast_id, mac) => {
2095                    self.collect_macro_def(attrs, ast_id, mac, module_id)
2096                }
2097                ModItemKind::Impl(ast_id, imp) => {
2098                    let impl_id =
2099                        ImplLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
2100                            .intern(db);
2101                    self.def_collector.def_map.modules[self.module_id]
2102                        .scope
2103                        .define_impl(impl_id, imp.is_trait_impl)
2104                }
2105                ModItemKind::Function(ast_id, it) => {
2106                    let fn_id =
2107                        FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), ast_id) }
2108                            .intern(db);
2109
2110                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2111
2112                    update_def(self.def_collector, fn_id.into(), &it.name, vis, None);
2113
2114                    if self.def_collector.def_map.block.is_none()
2115                        && self.def_collector.is_proc_macro
2116                        && self.module_id == self.def_collector.def_map.root
2117                        && let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name)
2118                    {
2119                        self.def_collector.export_proc_macro(
2120                            proc_macro,
2121                            InFile::new(self.file_id(), ast_id),
2122                            fn_id,
2123                        );
2124
2125                        // A proc macro is implemented as a function, but it's treated as a macro, not a function.
2126                        // You cannot call it like a function, for example, except in its defining crate.
2127                        // So we keep the function definition, but remove it from the scope, leaving only the macro.
2128                        self.def_collector.def_map[module_id]
2129                            .scope
2130                            .remove_from_value_ns(&it.name, fn_id.into());
2131                    }
2132                }
2133                ModItemKind::Struct(ast_id, it) => {
2134                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2135                    let value_ns_ctor_vis = match &it.value_ns_ctor {
2136                        StructValueNsCtor::NoValueNsCtor => None,
2137                        StructValueNsCtor::ValueNsCtorWithVis(vis) => {
2138                            Some(resolve_vis(def_map, local_def_map, &self.item_tree[*vis]))
2139                        }
2140                        StructValueNsCtor::ValueNsCtorWithMinVis(multiple) => multiple
2141                            .iter()
2142                            .map(|&vis| resolve_vis(def_map, local_def_map, &self.item_tree[vis]))
2143                            .fold(None, |a: Option<Visibility>, b| a?.min(db, b, def_map)),
2144                    };
2145                    let interned = StructLoc {
2146                        container: module_id,
2147                        id: InFile::new(self.tree_id.file_id(), ast_id),
2148                    }
2149                    .intern(db);
2150                    consider_deferred_derives(
2151                        self.tree_id.file_id(),
2152                        &mut self.def_collector.deferred_builtin_derives,
2153                        ast_id.upcast(),
2154                        interned.into(),
2155                        def_map,
2156                    );
2157                    update_def(
2158                        self.def_collector,
2159                        interned.into(),
2160                        &it.name,
2161                        vis,
2162                        value_ns_ctor_vis,
2163                    );
2164                }
2165                ModItemKind::Union(ast_id, it) => {
2166                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2167                    let interned = UnionLoc {
2168                        container: module_id,
2169                        id: InFile::new(self.tree_id.file_id(), ast_id),
2170                    }
2171                    .intern(db);
2172                    consider_deferred_derives(
2173                        self.tree_id.file_id(),
2174                        &mut self.def_collector.deferred_builtin_derives,
2175                        ast_id.upcast(),
2176                        interned.into(),
2177                        def_map,
2178                    );
2179                    update_def(self.def_collector, interned.into(), &it.name, vis, None);
2180                }
2181                ModItemKind::Enum(ast_id, it) => {
2182                    let enum_ = EnumLoc {
2183                        container: module_id,
2184                        id: InFile::new(self.tree_id.file_id(), ast_id),
2185                    }
2186                    .intern(db);
2187
2188                    consider_deferred_derives(
2189                        self.tree_id.file_id(),
2190                        &mut self.def_collector.deferred_builtin_derives,
2191                        ast_id.upcast(),
2192                        enum_.into(),
2193                        def_map,
2194                    );
2195                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2196                    update_def(self.def_collector, enum_.into(), &it.name, vis, None);
2197                }
2198                ModItemKind::Const(ast_id, it) => {
2199                    let const_id =
2200                        ConstLoc { container, id: InFile::new(self.tree_id.file_id(), ast_id) }
2201                            .intern(db);
2202
2203                    match &it.name {
2204                        Some(name) => {
2205                            let vis =
2206                                resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2207                            update_def(self.def_collector, const_id.into(), name, vis, None);
2208                        }
2209                        None => {
2210                            // const _: T = ...;
2211                            self.def_collector.def_map.modules[self.module_id]
2212                                .scope
2213                                .define_unnamed_const(const_id);
2214                        }
2215                    }
2216                }
2217                ModItemKind::Static(ast_id, it) => {
2218                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2219                    update_def(
2220                        self.def_collector,
2221                        StaticLoc { container, id: InFile::new(self.file_id(), ast_id) }
2222                            .intern(db)
2223                            .into(),
2224                        &it.name,
2225                        vis,
2226                        None,
2227                    );
2228                }
2229                ModItemKind::Trait(ast_id, it) => {
2230                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2231                    update_def(
2232                        self.def_collector,
2233                        TraitLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
2234                            .intern(db)
2235                            .into(),
2236                        &it.name,
2237                        vis,
2238                        None,
2239                    );
2240                }
2241                ModItemKind::TypeAlias(ast_id, it) => {
2242                    let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2243                    update_def(
2244                        self.def_collector,
2245                        TypeAliasLoc { container, id: InFile::new(self.file_id(), ast_id) }
2246                            .intern(db)
2247                            .into(),
2248                        &it.name,
2249                        vis,
2250                        None,
2251                    );
2252                }
2253            }
2254        };
2255
2256        // extern crates should be processed eagerly instead of deferred to resolving.
2257        // `#[macro_use] extern crate` is hoisted to imports macros before collecting
2258        // any other items.
2259        if is_crate_root {
2260            items
2261                .iter()
2262                .filter(move |&&it| matches!(item_tree.index(it), ModItemKind::ExternCrate(..)))
2263                .copied()
2264                .for_each(&mut process_mod_item);
2265            items
2266                .iter()
2267                .filter(move |&&it| !matches!(item_tree.index(it), ModItemKind::ExternCrate(..)))
2268                .copied()
2269                .for_each(process_mod_item);
2270        } else {
2271            items.iter().copied().for_each(process_mod_item);
2272        }
2273    }
2274
2275    fn process_macro_use_extern_crate<'a>(
2276        &mut self,
2277        extern_crate_id: ExternCrateId,
2278        macro_use_attrs: impl Iterator<Item = &'a Attr>,
2279        target_crate: Crate,
2280    ) {
2281        cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
2282        let mut single_imports = Vec::new();
2283        for attr in macro_use_attrs {
2284            let Some(paths) = attr.parse_path_comma_token_tree(self.def_collector.db) else {
2285                // `#[macro_use]` (without any paths) found, forget collected names and just import
2286                // all visible macros.
2287                self.def_collector.import_macros_from_extern_crate(
2288                    target_crate,
2289                    None,
2290                    Some(extern_crate_id),
2291                );
2292                return;
2293            };
2294            for (path, _, _) in paths {
2295                if let Some(name) = path.as_ident() {
2296                    single_imports.push(name.clone());
2297                }
2298            }
2299        }
2300
2301        self.def_collector.import_macros_from_extern_crate(
2302            target_crate,
2303            Some(single_imports),
2304            Some(extern_crate_id),
2305        );
2306    }
2307
2308    fn collect_module(
2309        &mut self,
2310        module_ast_id: ItemTreeAstId<Mod>,
2311        module: &Mod,
2312        attrs: Attrs<'_>,
2313    ) {
2314        let path_attr = attrs.by_key(sym::path).string_value_unescape();
2315        let is_macro_use = attrs.by_key(sym::macro_use).exists();
2316        match &module.kind {
2317            // inline module, just recurse
2318            ModKind::Inline { items } => {
2319                let module_id = self.push_child_module(
2320                    module.name.clone(),
2321                    module_ast_id,
2322                    None,
2323                    &self.item_tree[module.visibility],
2324                );
2325
2326                let Some(mod_dir) =
2327                    self.mod_dir.descend_into_definition(&module.name, path_attr.as_deref())
2328                else {
2329                    return;
2330                };
2331                ModCollector {
2332                    def_collector: &mut *self.def_collector,
2333                    macro_depth: self.macro_depth,
2334                    module_id,
2335                    tree_id: self.tree_id,
2336                    item_tree: self.item_tree,
2337                    mod_dir,
2338                }
2339                .collect_in_top_module(items);
2340                if is_macro_use {
2341                    self.import_all_legacy_macros(module_id);
2342                }
2343            }
2344            // out of line module, resolve, parse and recurse
2345            ModKind::Outline => {
2346                let ast_id = AstId::new(self.file_id(), module_ast_id);
2347                let db = self.def_collector.db;
2348                match self.mod_dir.resolve_declaration(
2349                    db,
2350                    self.file_id(),
2351                    &module.name,
2352                    path_attr.as_deref(),
2353                ) {
2354                    Ok((file_id, is_mod_rs, mod_dir)) => {
2355                        let item_tree =
2356                            file_item_tree(db, file_id.into(), self.def_collector.def_map.krate);
2357                        let top_level_attrs = item_tree.top_level_attrs();
2358                        match top_level_attrs {
2359                            Some(AttrsOrCfg::CfgDisabled(cfg)) => {
2360                                self.emit_unconfigured_diagnostic(
2361                                    InFile::new(self.file_id(), module_ast_id.erase()),
2362                                    &cfg.0,
2363                                );
2364                            }
2365                            Some(AttrsOrCfg::Enabled { .. }) | None => {
2366                                let module_id = self.push_child_module(
2367                                    module.name.clone(),
2368                                    ast_id.value,
2369                                    Some((file_id, is_mod_rs)),
2370                                    &self.item_tree[module.visibility],
2371                                );
2372                                ModCollector {
2373                                    def_collector: self.def_collector,
2374                                    macro_depth: self.macro_depth,
2375                                    module_id,
2376                                    tree_id: TreeId::new(file_id.into(), None),
2377                                    item_tree,
2378                                    mod_dir,
2379                                }
2380                                .collect_in_top_module(item_tree.top_level_items());
2381                                let is_macro_use = is_macro_use
2382                                    || matches!(top_level_attrs, Some(AttrsOrCfg::Enabled { attrs }) if attrs.as_ref().by_key(sym::macro_use).exists());
2383                                if is_macro_use {
2384                                    self.import_all_legacy_macros(module_id);
2385                                }
2386                            }
2387                        }
2388                    }
2389                    Err(candidates) => {
2390                        self.push_child_module(
2391                            module.name.clone(),
2392                            ast_id.value,
2393                            None,
2394                            &self.item_tree[module.visibility],
2395                        );
2396                        self.def_collector.def_map.diagnostics.push(
2397                            DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
2398                        );
2399                    }
2400                };
2401            }
2402        }
2403    }
2404
2405    fn push_child_module(
2406        &mut self,
2407        name: Name,
2408        declaration: FileAstId<ast::Module>,
2409        definition: Option<(EditionedFileId, bool)>,
2410        visibility: &crate::visibility::RawVisibility,
2411    ) -> ModuleId {
2412        let vis = self
2413            .def_collector
2414            .def_map
2415            .resolve_visibility(
2416                self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map),
2417                self.def_collector.db,
2418                self.module_id,
2419                visibility,
2420                false,
2421            )
2422            .unwrap_or(Visibility::Public);
2423        let origin = match definition {
2424            None => {
2425                ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id }
2426            }
2427            Some((definition, is_mod_rs)) => ModuleOrigin::File {
2428                declaration,
2429                definition,
2430                is_mod_rs,
2431                declaration_tree_id: self.tree_id,
2432            },
2433        };
2434
2435        let module = unsafe {
2436            crate::ModuleIdLt::new(
2437                self.def_collector.db,
2438                self.def_collector.def_map.krate,
2439                self.def_collector.def_map.block_id(),
2440                Some(self.module_id),
2441                name.clone(),
2442            )
2443            .to_static()
2444        };
2445        let def_map = &mut self.def_collector.def_map;
2446        let modules = &mut def_map.modules;
2447        let mut data = ModuleData::new(origin, vis, Some(self.module_id));
2448        for (name, macs) in modules[self.module_id].scope.legacy_macros() {
2449            for &mac in macs {
2450                data.scope.define_legacy_macro(name.clone(), mac);
2451            }
2452        }
2453        modules[self.module_id].children.insert(name.clone(), module);
2454        modules.insert(module, data);
2455
2456        let def = ModuleDefId::from(module);
2457
2458        def_map.modules[self.module_id].scope.declare(def);
2459        self.def_collector.update(
2460            self.module_id,
2461            &[(Some(name), PerNs::from_def(def, vis, None, None))],
2462            vis,
2463            None,
2464        );
2465        module
2466    }
2467
2468    /// Resolves attributes on an item.
2469    ///
2470    /// Returns `Err` when some attributes could not be resolved to builtins and have been
2471    /// registered as unresolved.
2472    ///
2473    /// If `ignore_up_to` is `Some`, attributes preceding and including that attribute will be
2474    /// assumed to be resolved already.
2475    fn resolve_attributes(
2476        &mut self,
2477        attrs: Attrs<'_>,
2478        mod_item: ModItemId,
2479        container: ItemContainerId,
2480    ) -> Result<(), ()> {
2481        let ignore_up_to =
2482            self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
2483        for (attr_id, attr) in attrs.iter_after(ignore_up_to) {
2484            if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
2485                continue;
2486            }
2487            tracing::debug!(
2488                "non-builtin attribute {}",
2489                attr.path.display(self.def_collector.db, Edition::LATEST)
2490            );
2491
2492            let ast_id = AstIdWithPath::new(
2493                self.file_id(),
2494                mod_item.ast_id(self.item_tree),
2495                attr.path.clone(),
2496            );
2497            self.def_collector.unresolved_macros.push(MacroDirective {
2498                module_id: self.module_id,
2499                depth: self.macro_depth + 1,
2500                kind: MacroDirectiveKind::Attr {
2501                    ast_id,
2502                    attr_id,
2503                    attr: attr.clone(),
2504                    mod_item,
2505                    tree: self.tree_id,
2506                    item_tree: self.item_tree,
2507                },
2508                container,
2509            });
2510
2511            return Err(());
2512        }
2513
2514        Ok(())
2515    }
2516
2517    fn collect_macro_rules(
2518        &mut self,
2519        attrs: Attrs<'_>,
2520        ast_id: ItemTreeAstId<MacroRules>,
2521        mac: &MacroRules,
2522        module: ModuleId,
2523    ) {
2524        let krate = self.def_collector.def_map.krate;
2525        let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2526
2527        let export_attr = || attrs.by_key(sym::macro_export);
2528
2529        let is_export = export_attr().exists();
2530        let local_inner = if is_export {
2531            export_attr().tt_values().flat_map(|it| it.iter()).any(|it| match it {
2532                tt::TtElement::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros,
2533                _ => false,
2534            })
2535        } else {
2536            false
2537        };
2538
2539        // Case 1: builtin macros
2540        let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2541            // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
2542            let name = match attrs.by_key(sym::rustc_builtin_macro).string_value_with_span() {
2543                Some((it, span)) => &Name::new_symbol(Symbol::intern(it), span.ctx),
2544                None => {
2545                    let explicit_name =
2546                        attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
2547                            match tt.token_trees().iter().next() {
2548                                Some(tt::TtElement::Leaf(tt::Leaf::Ident(name))) => Some(name),
2549                                _ => None,
2550                            }
2551                        });
2552                    match explicit_name {
2553                        Some(ident) => &ident.as_name(),
2554                        None => &mac.name,
2555                    }
2556                }
2557            };
2558            match find_builtin_macro(name) {
2559                Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
2560                Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
2561                None => {
2562                    self.def_collector
2563                        .def_map
2564                        .diagnostics
2565                        .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2566                    MacroExpander::UnimplementedBuiltIn
2567                }
2568            }
2569        } else {
2570            // Case 2: normal `macro_rules!` macro
2571            let id = InFile::new(self.file_id(), ast_id);
2572            let decl_expander = id.upcast().decl_macro_expander(self.def_collector.db, krate);
2573            let styles = decl_expander.mac.rule_styles();
2574            MacroExpander::Declarative { styles }
2575        };
2576        let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2577
2578        let mut flags = MacroRulesLocFlags::empty();
2579        flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
2580        flags.set(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE, allow_internal_unsafe);
2581
2582        let macro_id = MacroRulesLoc {
2583            container: module,
2584            id: InFile::new(self.file_id(), ast_id),
2585            flags,
2586            expander,
2587            edition: self.def_collector.def_map.data.edition,
2588        }
2589        .intern(self.def_collector.db);
2590        self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2591        self.def_collector.define_macro_rules(
2592            self.module_id,
2593            mac.name.clone(),
2594            macro_id,
2595            is_export,
2596        );
2597    }
2598
2599    fn collect_macro_def(
2600        &mut self,
2601        attrs: Attrs<'_>,
2602        ast_id: ItemTreeAstId<Macro2>,
2603        mac: &Macro2,
2604        module: ModuleId,
2605    ) {
2606        let krate = self.def_collector.def_map.krate;
2607        let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2608
2609        // Case 1: builtin macros
2610        let mut helpers_opt = None;
2611        let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2612            if let Some(expander) = find_builtin_macro(&mac.name) {
2613                match expander {
2614                    Either::Left(it) => MacroExpander::BuiltIn(it),
2615                    Either::Right(it) => MacroExpander::BuiltInEager(it),
2616                }
2617            } else if let Some(expander) = find_builtin_derive(&mac.name) {
2618                if let Some(attr) = attrs.by_key(sym::rustc_builtin_macro).tt_values().next() {
2619                    // NOTE: The item *may* have both `#[rustc_builtin_macro]` and `#[proc_macro_derive]`,
2620                    // in which case rustc ignores the helper attributes from the latter, but it
2621                    // "doesn't make sense in practice" (see rust-lang/rust#87027).
2622                    if let Some((name, helpers)) = parse_macro_name_and_helper_attrs(attr) {
2623                        // NOTE: rustc overrides the name if the macro name if it's different from the
2624                        // macro name, but we assume it isn't as there's no such case yet. FIXME if
2625                        // the following assertion fails.
2626                        stdx::always!(
2627                            name == mac.name,
2628                            "built-in macro {} has #[rustc_builtin_macro] which declares different name {}",
2629                            mac.name.display(self.def_collector.db, Edition::LATEST),
2630                            name.display(self.def_collector.db, Edition::LATEST),
2631                        );
2632                        helpers_opt = Some(helpers);
2633                    }
2634                }
2635                MacroExpander::BuiltInDerive(expander)
2636            } else if let Some(expander) = find_builtin_attr(&mac.name) {
2637                MacroExpander::BuiltInAttr(expander)
2638            } else {
2639                self.def_collector
2640                    .def_map
2641                    .diagnostics
2642                    .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2643                MacroExpander::UnimplementedBuiltIn
2644            }
2645        } else {
2646            // Case 2: normal `macro`
2647            let id = InFile::new(self.file_id(), ast_id);
2648            let decl_expander = id.upcast().decl_macro_expander(self.def_collector.db, krate);
2649            let styles = decl_expander.mac.rule_styles();
2650            MacroExpander::Declarative { styles }
2651        };
2652        let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2653
2654        let macro_id = Macro2Loc {
2655            container: module,
2656            id: InFile::new(self.file_id(), ast_id),
2657            expander,
2658            allow_internal_unsafe,
2659            edition: self.def_collector.def_map.data.edition,
2660        }
2661        .intern(self.def_collector.db);
2662        self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2663        self.def_collector.define_macro_def(
2664            self.module_id,
2665            mac.name.clone(),
2666            macro_id,
2667            &self.item_tree[mac.visibility],
2668        );
2669        if let Some(helpers) = helpers_opt
2670            && self.def_collector.def_map.block.is_none()
2671        {
2672            Arc::get_mut(&mut self.def_collector.def_map.data)
2673                .unwrap()
2674                .exported_derives
2675                .insert(macro_id.into(), helpers);
2676        }
2677    }
2678
2679    fn collect_macro_call(
2680        &mut self,
2681        ast_id: FileAstId<ast::MacroCall>,
2682        macro_call: &MacroCall,
2683        container: ItemContainerId,
2684    ) {
2685        let &MacroCall { ref path, expand_to, ctxt } = macro_call;
2686        let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone());
2687        let db = self.def_collector.db;
2688
2689        // FIXME: Immediately expanding in "Case 1" is insufficient since "Case 2" may also define
2690        // new legacy macros that create textual scopes. We need a way to resolve names in textual
2691        // scopes without eager expansion.
2692
2693        let mut eager_callback_buffer = vec![];
2694        // Case 1: try to resolve macro calls with single-segment name and expand macro_rules
2695        if let Ok(res) = macro_call_as_call_id(
2696            db,
2697            ast_id.ast_id,
2698            &ast_id.path,
2699            ctxt,
2700            expand_to,
2701            self.def_collector.def_map.krate,
2702            self.macro_depth + 1,
2703            self.def_collector.def_map.recursion_limit(),
2704            |path| {
2705                path.as_ident().and_then(|name| {
2706                    let def_map = &self.def_collector.def_map;
2707                    def_map
2708                        .with_ancestor_maps(db, self.module_id, &mut |map, module| {
2709                            map[module].scope.get_legacy_macro(name)?.last().copied()
2710                        })
2711                        .or_else(|| def_map[self.module_id].scope.get(name).take_macros())
2712                        .or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0))
2713                        .filter(|&id| sub_namespace_match(db, id, Some(MacroSubNs::Bang)))
2714                        .map(|it| it.definition(self.def_collector.db))
2715                })
2716            },
2717            &mut |ptr, call_id| eager_callback_buffer.push((ptr, call_id)),
2718        ) {
2719            for (ptr, call_id) in eager_callback_buffer {
2720                self.def_collector.def_map.modules[self.module_id]
2721                    .scope
2722                    .add_macro_invoc(ptr.map(|(_, it)| it), call_id);
2723            }
2724            // FIXME: if there were errors, this might've been in the eager expansion from an
2725            // unresolved macro, so we need to push this into late macro resolution. see fixme above
2726            if res.err.is_none() {
2727                // Legacy macros need to be expanded immediately, so that any macros they produce
2728                // are in scope.
2729                if let Some(call_id) = res.value {
2730                    self.def_collector.def_map.modules[self.module_id]
2731                        .scope
2732                        .add_macro_invoc(ast_id.ast_id, call_id);
2733                    self.def_collector.collect_macro_expansion(
2734                        self.module_id,
2735                        call_id,
2736                        self.macro_depth + 1,
2737                        container,
2738                        None,
2739                    );
2740                }
2741
2742                return;
2743            }
2744        }
2745
2746        // Case 2: resolve in module scope, expand during name resolution.
2747        self.def_collector.unresolved_macros.push(MacroDirective {
2748            module_id: self.module_id,
2749            depth: self.macro_depth + 1,
2750            kind: MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt },
2751            container,
2752        });
2753    }
2754
2755    fn import_all_legacy_macros(&mut self, module_id: ModuleId) {
2756        let [Some(source), Some(target)] =
2757            self.def_collector.def_map.modules.get_disjoint_mut([&module_id, &self.module_id])
2758        else {
2759            return;
2760        };
2761
2762        for (name, macs) in source.scope.legacy_macros() {
2763            if let Some(&mac) = macs.last() {
2764                target.scope.define_legacy_macro(name.clone(), mac);
2765            }
2766        }
2767    }
2768
2769    fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedAstId, cfg: &CfgExpr) {
2770        self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2771            self.module_id,
2772            ast_id,
2773            cfg.clone(),
2774            self.def_collector.cfg_options.clone(),
2775        ));
2776    }
2777
2778    #[inline]
2779    fn file_id(&self) -> HirFileId {
2780        self.tree_id.file_id()
2781    }
2782}
2783
2784#[cfg(test)]
2785mod tests {
2786    use test_fixture::WithFixture;
2787
2788    use crate::test_db::TestDB;
2789
2790    use super::*;
2791
2792    fn do_resolve(not_ra_fixture: &str) {
2793        let (db, _) = TestDB::with_single_file(not_ra_fixture);
2794        let krate = db.test_crate();
2795
2796        crate_def_map(&db, krate);
2797    }
2798
2799    #[test]
2800    fn test_macro_expand_will_stop_1() {
2801        do_resolve(
2802            r#"
2803macro_rules! foo {
2804    ($($ty:ty)*) => { foo!($($ty)*); }
2805}
2806foo!(KABOOM);
2807"#,
2808        );
2809        do_resolve(
2810            r#"
2811macro_rules! foo {
2812    ($($ty:ty)*) => { foo!(() $($ty)*); }
2813}
2814foo!(KABOOM);
2815"#,
2816        );
2817    }
2818
2819    #[ignore]
2820    #[test]
2821    fn test_macro_expand_will_stop_2() {
2822        // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2823        // the release mode. That's why the argument is not an ra_fixture --
2824        // otherwise injection highlighting gets stuck.
2825        //
2826        // We need to find a way to fail this faster!
2827        do_resolve(
2828            r#"
2829macro_rules! foo {
2830    ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2831}
2832foo!(KABOOM);
2833"#,
2834        );
2835    }
2836
2837    #[test]
2838    fn crate_attrs() {
2839        let fixture = r#"
2840//- /lib.rs crate:foo crate-attr:recursion_limit="4" crate-attr:no_core crate-attr:no_std crate-attr:feature(register_tool)
2841        "#;
2842        let (db, _) = TestDB::with_single_file(fixture);
2843        let def_map = crate_def_map(&db, db.test_crate());
2844        assert_eq!(def_map.recursion_limit(), 4);
2845        assert!(def_map.is_no_core());
2846        assert!(def_map.is_no_std());
2847        assert!(def_map.features().is_enabled(&sym::register_tool));
2848    }
2849}