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