]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/nameres/collector.rs
Simplify
[rust.git] / crates / hir_def / src / 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
6 use std::{iter, mem};
7
8 use base_db::{CrateId, Edition, FileId};
9 use cfg::{CfgExpr, CfgOptions};
10 use either::Either;
11 use hir_expand::{
12     ast_id_map::FileAstId,
13     builtin_attr_macro::find_builtin_attr,
14     builtin_derive_macro::find_builtin_derive,
15     builtin_fn_macro::find_builtin_macro,
16     name::{name, AsName, Name},
17     proc_macro::ProcMacroExpander,
18     ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
19     MacroDefKind,
20 };
21 use itertools::Itertools;
22 use la_arena::Idx;
23 use limit::Limit;
24 use rustc_hash::{FxHashMap, FxHashSet};
25 use syntax::{ast, SmolStr};
26
27 use crate::{
28     attr::{Attr, AttrId, Attrs},
29     attr_macro_as_call_id,
30     db::DefDatabase,
31     derive_macro_as_call_id,
32     intern::Interned,
33     item_scope::{ImportType, PerNsGlobImports},
34     item_tree::{
35         self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
36         MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
37     },
38     macro_call_as_call_id, macro_id_to_def_id,
39     nameres::{
40         diagnostics::DefDiagnostic,
41         mod_resolution::ModDir,
42         path_resolution::ReachedFixedPoint,
43         proc_macro::{ProcMacroDef, ProcMacroKind},
44         BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
45     },
46     path::{ImportAlias, ModPath, PathKind},
47     per_ns::PerNs,
48     visibility::{RawVisibility, Visibility},
49     AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionId,
50     FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc,
51     MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId,
52     ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro,
53 };
54
55 static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
56 static EXPANSION_DEPTH_LIMIT: Limit = Limit::new(128);
57 static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
58
59 pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: TreeId) -> DefMap {
60     let crate_graph = db.crate_graph();
61
62     let mut deps = FxHashMap::default();
63     // populate external prelude and dependency list
64     let krate = &crate_graph[def_map.krate];
65     for dep in &krate.dependencies {
66         tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
67         let dep_def_map = db.crate_def_map(dep.crate_id);
68         let dep_root = dep_def_map.module_id(dep_def_map.root);
69
70         deps.insert(dep.as_name(), dep_root.into());
71
72         if dep.is_prelude() && !tree_id.is_block() {
73             def_map.extern_prelude.insert(dep.as_name(), dep_root);
74         }
75     }
76
77     let cfg_options = &krate.cfg_options;
78     let proc_macros = krate
79         .proc_macro
80         .iter()
81         .enumerate()
82         .map(|(idx, it)| {
83             // FIXME: a hacky way to create a Name from string.
84             let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
85             (
86                 name.as_name(),
87                 ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
88             )
89         })
90         .collect();
91     let is_proc_macro = krate.is_proc_macro;
92
93     let mut collector = DefCollector {
94         db,
95         def_map,
96         deps,
97         glob_imports: FxHashMap::default(),
98         unresolved_imports: Vec::new(),
99         resolved_imports: Vec::new(),
100         unresolved_macros: Vec::new(),
101         mod_dirs: FxHashMap::default(),
102         cfg_options,
103         proc_macros,
104         from_glob_import: Default::default(),
105         skip_attrs: Default::default(),
106         derive_helpers_in_scope: Default::default(),
107         is_proc_macro,
108     };
109     if tree_id.is_block() {
110         collector.seed_with_inner(tree_id);
111     } else {
112         collector.seed_with_top_level();
113     }
114     collector.collect();
115     let mut def_map = collector.finish();
116     def_map.shrink_to_fit();
117     def_map
118 }
119
120 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
121 enum 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
130 impl 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)]
140 enum ImportSource {
141     Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> },
142     ExternCrate(ItemTreeId<item_tree::ExternCrate>),
143 }
144
145 #[derive(Clone, Debug, Eq, PartialEq)]
146 struct Import {
147     path: Interned<ModPath>,
148     alias: Option<ImportAlias>,
149     visibility: RawVisibility,
150     kind: ImportKind,
151     is_prelude: bool,
152     is_extern_crate: bool,
153     is_macro_use: bool,
154     source: ImportSource,
155 }
156
157 impl Import {
158     fn from_use(
159         db: &dyn DefDatabase,
160         krate: CrateId,
161         tree: &ItemTree,
162         id: ItemTreeId<item_tree::Import>,
163     ) -> Vec<Self> {
164         let it = &tree[id.value];
165         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
166         let visibility = &tree[it.visibility];
167         let is_prelude = attrs.by_key("prelude_import").exists();
168
169         let mut res = Vec::new();
170         it.use_tree.expand(|idx, path, kind, alias| {
171             res.push(Self {
172                 path: Interned::new(path), // FIXME this makes little sense
173                 alias,
174                 visibility: visibility.clone(),
175                 kind,
176                 is_prelude,
177                 is_extern_crate: false,
178                 is_macro_use: false,
179                 source: ImportSource::Import { id, use_tree: idx },
180             });
181         });
182         res
183     }
184
185     fn from_extern_crate(
186         db: &dyn DefDatabase,
187         krate: CrateId,
188         tree: &ItemTree,
189         id: ItemTreeId<item_tree::ExternCrate>,
190     ) -> Self {
191         let it = &tree[id.value];
192         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
193         let visibility = &tree[it.visibility];
194         Self {
195             path: Interned::new(ModPath::from_segments(
196                 PathKind::Plain,
197                 iter::once(it.name.clone()),
198             )),
199             alias: it.alias.clone(),
200             visibility: visibility.clone(),
201             kind: ImportKind::Plain,
202             is_prelude: false,
203             is_extern_crate: true,
204             is_macro_use: attrs.by_key("macro_use").exists(),
205             source: ImportSource::ExternCrate(id),
206         }
207     }
208 }
209
210 #[derive(Clone, Debug, Eq, PartialEq)]
211 struct ImportDirective {
212     module_id: LocalModuleId,
213     import: Import,
214     status: PartialResolvedImport,
215 }
216
217 #[derive(Clone, Debug, Eq, PartialEq)]
218 struct MacroDirective {
219     module_id: LocalModuleId,
220     depth: usize,
221     kind: MacroDirectiveKind,
222     container: ItemContainerId,
223 }
224
225 #[derive(Clone, Debug, Eq, PartialEq)]
226 enum MacroDirectiveKind {
227     FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
228     Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize },
229     Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
230 }
231
232 /// Walks the tree of module recursively
233 struct DefCollector<'a> {
234     db: &'a dyn DefDatabase,
235     def_map: DefMap,
236     deps: FxHashMap<Name, ModuleId>,
237     glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
238     unresolved_imports: Vec<ImportDirective>,
239     resolved_imports: Vec<ImportDirective>,
240     unresolved_macros: Vec<MacroDirective>,
241     mod_dirs: FxHashMap<LocalModuleId, ModDir>,
242     cfg_options: &'a CfgOptions,
243     /// List of procedural macros defined by this crate. This is read from the dynamic library
244     /// built by the build system, and is the list of proc. macros we can actually expand. It is
245     /// empty when proc. macro support is disabled (in which case we still do name resolution for
246     /// them).
247     proc_macros: Vec<(Name, ProcMacroExpander)>,
248     is_proc_macro: bool,
249     from_glob_import: PerNsGlobImports,
250     /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
251     /// This map is used to skip all attributes up to and including the one that failed to resolve,
252     /// in order to not expand them twice.
253     ///
254     /// This also stores the attributes to skip when we resolve derive helpers and non-macro
255     /// non-builtin attributes in general.
256     skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
257     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
258     /// attributes.
259     derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
260 }
261
262 impl DefCollector<'_> {
263     fn seed_with_top_level(&mut self) {
264         let _p = profile::span("seed_with_top_level");
265
266         let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
267         let item_tree = self.db.file_item_tree(file_id.into());
268         let module_id = self.def_map.root;
269
270         let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
271         if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
272             self.inject_prelude(&attrs);
273
274             // Process other crate-level attributes.
275             for attr in &*attrs {
276                 let attr_name = match attr.path.as_ident() {
277                     Some(name) => name,
278                     None => continue,
279                 };
280
281                 if *attr_name == hir_expand::name![recursion_limit] {
282                     if let Some(limit) = attr.string_value() {
283                         if let Ok(limit) = limit.parse() {
284                             self.def_map.recursion_limit = Some(limit);
285                         }
286                     }
287                     continue;
288                 }
289
290                 if *attr_name == hir_expand::name![crate_type] {
291                     if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
292                         self.is_proc_macro = true;
293                     }
294                     continue;
295                 }
296
297                 let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
298                     || *attr_name == hir_expand::name![register_tool];
299                 if !attr_is_register_like {
300                     continue;
301                 }
302
303                 let registered_name = match attr.single_ident_value() {
304                     Some(ident) => ident.as_name(),
305                     _ => continue,
306                 };
307
308                 if *attr_name == hir_expand::name![register_attr] {
309                     self.def_map.registered_attrs.push(registered_name.to_smol_str());
310                     cov_mark::hit!(register_attr);
311                 } else {
312                     self.def_map.registered_tools.push(registered_name.to_smol_str());
313                     cov_mark::hit!(register_tool);
314                 }
315             }
316
317             ModCollector {
318                 def_collector: self,
319                 macro_depth: 0,
320                 module_id,
321                 tree_id: TreeId::new(file_id.into(), None),
322                 item_tree: &item_tree,
323                 mod_dir: ModDir::root(),
324             }
325             .collect_in_top_module(item_tree.top_level_items());
326         }
327     }
328
329     fn seed_with_inner(&mut self, tree_id: TreeId) {
330         let item_tree = tree_id.item_tree(self.db);
331         let module_id = self.def_map.root;
332
333         let is_cfg_enabled = item_tree
334             .top_level_attrs(self.db, self.def_map.krate)
335             .cfg()
336             .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
337         if is_cfg_enabled {
338             ModCollector {
339                 def_collector: self,
340                 macro_depth: 0,
341                 module_id,
342                 tree_id,
343                 item_tree: &item_tree,
344                 mod_dir: ModDir::root(),
345             }
346             .collect_in_top_module(item_tree.top_level_items());
347         }
348     }
349
350     fn resolution_loop(&mut self) {
351         let _p = profile::span("DefCollector::resolution_loop");
352
353         // main name resolution fixed-point loop.
354         let mut i = 0;
355         'outer: loop {
356             loop {
357                 self.db.unwind_if_cancelled();
358                 {
359                     let _p = profile::span("resolve_imports loop");
360                     loop {
361                         if self.resolve_imports() == ReachedFixedPoint::Yes {
362                             break;
363                         }
364                     }
365                 }
366                 if self.resolve_macros() == ReachedFixedPoint::Yes {
367                     break;
368                 }
369
370                 i += 1;
371                 if FIXED_POINT_LIMIT.check(i).is_err() {
372                     tracing::error!("name resolution is stuck");
373                     break 'outer;
374                 }
375             }
376
377             if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
378                 break;
379             }
380         }
381     }
382
383     fn collect(&mut self) {
384         let _p = profile::span("DefCollector::collect");
385
386         self.resolution_loop();
387
388         // Resolve all indeterminate resolved imports again
389         // As some of the macros will expand newly import shadowing partial resolved imports
390         // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
391         // correctly
392         let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
393             if let PartialResolvedImport::Indeterminate(_) = directive.status {
394                 let mut directive = directive.clone();
395                 directive.status = PartialResolvedImport::Unresolved;
396                 Some(directive)
397             } else {
398                 None
399             }
400         });
401         self.unresolved_imports.extend(partial_resolved);
402         self.resolve_imports();
403
404         let unresolved_imports = mem::take(&mut self.unresolved_imports);
405         // show unresolved imports in completion, etc
406         for directive in &unresolved_imports {
407             self.record_resolved_import(directive);
408         }
409         self.unresolved_imports = unresolved_imports;
410
411         if self.is_proc_macro {
412             // A crate exporting procedural macros is not allowed to export anything else.
413             //
414             // Additionally, while the proc macro entry points must be `pub`, they are not publicly
415             // exported in type/value namespace. This function reduces the visibility of all items
416             // in the crate root that aren't proc macros.
417             let root = self.def_map.root;
418             let module_id = self.def_map.module_id(root);
419             let root = &mut self.def_map.modules[root];
420             root.scope.censor_non_proc_macros(module_id);
421         }
422     }
423
424     /// When the fixed-point loop reaches a stable state, we might still have some unresolved
425     /// attributes (or unexpanded attribute proc macros) left over. This takes one of them, and
426     /// feeds the item it's applied to back into name resolution.
427     ///
428     /// This effectively ignores the fact that the macro is there and just treats the items as
429     /// normal code.
430     ///
431     /// This improves UX when proc macros are turned off or don't work, and replicates the behavior
432     /// before we supported proc. attribute macros.
433     fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
434         cov_mark::hit!(unresolved_attribute_fallback);
435
436         let mut unresolved_macros = mem::take(&mut self.unresolved_macros);
437         let pos = unresolved_macros.iter().position(|directive| {
438             if let MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } = &directive.kind {
439                 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
440
441                 let item_tree = tree.item_tree(self.db);
442                 let mod_dir = self.mod_dirs[&directive.module_id].clone();
443                 ModCollector {
444                     def_collector: self,
445                     macro_depth: directive.depth,
446                     module_id: directive.module_id,
447                     tree_id: *tree,
448                     item_tree: &item_tree,
449                     mod_dir,
450                 }
451                 .collect(&[*mod_item], directive.container);
452                 true
453             } else {
454                 false
455             }
456         });
457
458         if let Some(pos) = pos {
459             unresolved_macros.swap_remove(pos);
460         }
461
462         self.unresolved_macros.extend(unresolved_macros);
463
464         if pos.is_some() {
465             // Continue name resolution with the new data.
466             ReachedFixedPoint::No
467         } else {
468             ReachedFixedPoint::Yes
469         }
470     }
471
472     fn inject_prelude(&mut self, crate_attrs: &Attrs) {
473         // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
474
475         if crate_attrs.by_key("no_core").exists() {
476             // libcore does not get a prelude.
477             return;
478         }
479
480         let krate = if crate_attrs.by_key("no_std").exists() {
481             name![core]
482         } else {
483             let std = name![std];
484             if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
485                 std
486             } else {
487                 // If `std` does not exist for some reason, fall back to core. This mostly helps
488                 // keep r-a's own tests minimal.
489                 name![core]
490             }
491         };
492
493         let edition = match self.def_map.edition {
494             Edition::Edition2015 => name![rust_2015],
495             Edition::Edition2018 => name![rust_2018],
496             Edition::Edition2021 => name![rust_2021],
497         };
498
499         let path_kind = if self.def_map.edition == Edition::Edition2015 {
500             PathKind::Plain
501         } else {
502             PathKind::Abs
503         };
504         let path =
505             ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
506         // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
507         // FIXME remove this fallback
508         let fallback_path =
509             ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].into_iter());
510
511         for path in &[path, fallback_path] {
512             let (per_ns, _) = self.def_map.resolve_path(
513                 self.db,
514                 self.def_map.root,
515                 path,
516                 BuiltinShadowMode::Other,
517             );
518
519             match per_ns.types {
520                 Some((ModuleDefId::ModuleId(m), _)) => {
521                     self.def_map.prelude = Some(m);
522                     return;
523                 }
524                 types => {
525                     tracing::debug!(
526                         "could not resolve prelude path `{}` to module (resolved to {:?})",
527                         path,
528                         types
529                     );
530                 }
531             }
532         }
533     }
534
535     /// Adds a definition of procedural macro `name` to the root module.
536     ///
537     /// # Notes on procedural macro resolution
538     ///
539     /// Procedural macro functionality is provided by the build system: It has to build the proc
540     /// macro and pass the resulting dynamic library to rust-analyzer.
541     ///
542     /// When procedural macro support is enabled, the list of proc macros exported by a crate is
543     /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
544     /// derived from the dynamic library.
545     ///
546     /// However, we *also* would like to be able to at least *resolve* macros on our own, without
547     /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
548     /// use a dummy expander that always errors. This comes with the drawback of macros potentially
549     /// going out of sync with what the build system sees (since we resolve using VFS state, but
550     /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
551     fn export_proc_macro(
552         &mut self,
553         def: ProcMacroDef,
554         id: ItemTreeId<item_tree::Function>,
555         fn_id: FunctionId,
556         module_id: ModuleId,
557     ) {
558         let kind = def.kind.to_basedb_kind();
559         let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
560             Some(&(_, expander)) => (expander, kind),
561             None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
562         };
563
564         let proc_macro_id =
565             ProcMacroLoc { container: module_id, id, expander, kind }.intern(self.db);
566         self.define_proc_macro(def.name.clone(), proc_macro_id);
567         if let ProcMacroKind::CustomDerive { helpers } = def.kind {
568             self.def_map
569                 .exported_derives
570                 .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers);
571         }
572         self.def_map.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
573     }
574
575     /// Define a macro with `macro_rules`.
576     ///
577     /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
578     /// then it is also defined in the root module scope.
579     /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
580     ///
581     /// It is surprising that the macro will never be in the current module scope.
582     /// These code fails with "unresolved import/macro",
583     /// ```rust,compile_fail
584     /// mod m { macro_rules! foo { () => {} } }
585     /// use m::foo as bar;
586     /// ```
587     ///
588     /// ```rust,compile_fail
589     /// macro_rules! foo { () => {} }
590     /// self::foo!();
591     /// crate::foo!();
592     /// ```
593     ///
594     /// Well, this code compiles, because the plain path `foo` in `use` is searched
595     /// in the legacy textual scope only.
596     /// ```rust
597     /// macro_rules! foo { () => {} }
598     /// use foo as bar;
599     /// ```
600     fn define_macro_rules(
601         &mut self,
602         module_id: LocalModuleId,
603         name: Name,
604         macro_: MacroRulesId,
605         export: bool,
606     ) {
607         // Textual scoping
608         self.define_legacy_macro(module_id, name.clone(), macro_.into());
609
610         // Module scoping
611         // In Rust, `#[macro_export]` macros are unconditionally visible at the
612         // crate root, even if the parent modules is **not** visible.
613         if export {
614             let module_id = self.def_map.root;
615             self.def_map.modules[module_id].scope.declare(macro_.into());
616             self.update(
617                 module_id,
618                 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
619                 Visibility::Public,
620                 ImportType::Named,
621             );
622         }
623     }
624
625     /// Define a legacy textual scoped macro in module
626     ///
627     /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
628     /// It will clone all macros from parent legacy scope, whose definition is prior to
629     /// the definition of current module.
630     /// And also, `macro_use` on a module will import all legacy macros visible inside to
631     /// current legacy scope, with possible shadowing.
632     fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroId) {
633         // Always shadowing
634         self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
635     }
636
637     /// Define a macro 2.0 macro
638     ///
639     /// The scoped of macro 2.0 macro is equal to normal function
640     fn define_macro_def(
641         &mut self,
642         module_id: LocalModuleId,
643         name: Name,
644         macro_: Macro2Id,
645         vis: &RawVisibility,
646     ) {
647         let vis =
648             self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
649         self.def_map.modules[module_id].scope.declare(macro_.into());
650         self.update(
651             module_id,
652             &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
653             vis,
654             ImportType::Named,
655         );
656     }
657
658     /// Define a proc macro
659     ///
660     /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
661     /// And unconditionally exported.
662     fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
663         let module_id = self.def_map.root;
664         self.def_map.modules[module_id].scope.declare(macro_.into());
665         self.update(
666             module_id,
667             &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
668             Visibility::Public,
669             ImportType::Named,
670         );
671     }
672
673     /// Import macros from `#[macro_use] extern crate`.
674     fn import_macros_from_extern_crate(
675         &mut self,
676         current_module_id: LocalModuleId,
677         extern_crate: &item_tree::ExternCrate,
678     ) {
679         tracing::debug!(
680             "importing macros from extern crate: {:?} ({:?})",
681             extern_crate,
682             self.def_map.edition,
683         );
684
685         if let Some(m) = self.resolve_extern_crate(&extern_crate.name) {
686             if m == self.def_map.module_id(current_module_id) {
687                 cov_mark::hit!(ignore_macro_use_extern_crate_self);
688                 return;
689             }
690
691             cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
692             self.import_all_macros_exported(current_module_id, m.krate);
693         }
694     }
695
696     /// Import all exported macros from another crate
697     ///
698     /// Exported macros are just all macros in the root module scope.
699     /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
700     /// created by `use` in the root module, ignoring the visibility of `use`.
701     fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
702         let def_map = self.db.crate_def_map(krate);
703         for (name, def) in def_map[def_map.root].scope.macros() {
704             // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
705             self.define_legacy_macro(current_module_id, name.clone(), def);
706         }
707     }
708
709     /// Tries to resolve every currently unresolved import.
710     fn resolve_imports(&mut self) -> ReachedFixedPoint {
711         let mut res = ReachedFixedPoint::Yes;
712         let imports = mem::take(&mut self.unresolved_imports);
713         let imports = imports
714             .into_iter()
715             .filter_map(|mut directive| {
716                 directive.status = self.resolve_import(directive.module_id, &directive.import);
717                 match directive.status {
718                     PartialResolvedImport::Indeterminate(_) => {
719                         self.record_resolved_import(&directive);
720                         // FIXME: For avoid performance regression,
721                         // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
722                         self.resolved_imports.push(directive);
723                         res = ReachedFixedPoint::No;
724                         None
725                     }
726                     PartialResolvedImport::Resolved(_) => {
727                         self.record_resolved_import(&directive);
728                         self.resolved_imports.push(directive);
729                         res = ReachedFixedPoint::No;
730                         None
731                     }
732                     PartialResolvedImport::Unresolved => Some(directive),
733                 }
734             })
735             .collect();
736         self.unresolved_imports = imports;
737         res
738     }
739
740     fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
741         let _p = profile::span("resolve_import").detail(|| format!("{}", import.path));
742         tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
743         if import.is_extern_crate {
744             let name = import
745                 .path
746                 .as_ident()
747                 .expect("extern crate should have been desugared to one-element path");
748
749             let res = self.resolve_extern_crate(name);
750
751             match res {
752                 Some(res) => {
753                     PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
754                 }
755                 None => PartialResolvedImport::Unresolved,
756             }
757         } else {
758             let res = self.def_map.resolve_path_fp_with_macro(
759                 self.db,
760                 ResolveMode::Import,
761                 module_id,
762                 &import.path,
763                 BuiltinShadowMode::Module,
764             );
765
766             let def = res.resolved_def;
767             if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
768                 return PartialResolvedImport::Unresolved;
769             }
770
771             if let Some(krate) = res.krate {
772                 if krate != self.def_map.krate {
773                     return PartialResolvedImport::Resolved(
774                         def.filter_visibility(|v| matches!(v, Visibility::Public)),
775                     );
776                 }
777             }
778
779             // Check whether all namespace is resolved
780             if def.take_types().is_some()
781                 && def.take_values().is_some()
782                 && def.take_macros().is_some()
783             {
784                 PartialResolvedImport::Resolved(def)
785             } else {
786                 PartialResolvedImport::Indeterminate(def)
787             }
788         }
789     }
790
791     fn resolve_extern_crate(&self, name: &Name) -> Option<ModuleId> {
792         if *name == name!(self) {
793             cov_mark::hit!(extern_crate_self_as);
794             let root = match self.def_map.block {
795                 Some(_) => {
796                     let def_map = self.def_map.crate_root(self.db).def_map(self.db);
797                     def_map.module_id(def_map.root())
798                 }
799                 None => self.def_map.module_id(self.def_map.root()),
800             };
801             Some(root)
802         } else {
803             self.deps.get(name).copied()
804         }
805     }
806
807     fn record_resolved_import(&mut self, directive: &ImportDirective) {
808         let _p = profile::span("record_resolved_import");
809
810         let module_id = directive.module_id;
811         let import = &directive.import;
812         let mut def = directive.status.namespaces();
813         let vis = self
814             .def_map
815             .resolve_visibility(self.db, module_id, &directive.import.visibility)
816             .unwrap_or(Visibility::Public);
817
818         match import.kind {
819             ImportKind::Plain | ImportKind::TypeOnly => {
820                 let name = match &import.alias {
821                     Some(ImportAlias::Alias(name)) => Some(name),
822                     Some(ImportAlias::Underscore) => None,
823                     None => match import.path.segments().last() {
824                         Some(last_segment) => Some(last_segment),
825                         None => {
826                             cov_mark::hit!(bogus_paths);
827                             return;
828                         }
829                     },
830                 };
831
832                 if import.kind == ImportKind::TypeOnly {
833                     def.values = None;
834                     def.macros = None;
835                 }
836
837                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
838
839                 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
840                 if import.is_extern_crate && module_id == self.def_map.root {
841                     if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
842                     {
843                         self.def_map.extern_prelude.insert(name.clone(), def);
844                     }
845                 }
846
847                 self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named);
848             }
849             ImportKind::Glob => {
850                 tracing::debug!("glob import: {:?}", import);
851                 match def.take_types() {
852                     Some(ModuleDefId::ModuleId(m)) => {
853                         if import.is_prelude {
854                             // Note: This dodgily overrides the injected prelude. The rustc
855                             // implementation seems to work the same though.
856                             cov_mark::hit!(std_prelude);
857                             self.def_map.prelude = Some(m);
858                         } else if m.krate != self.def_map.krate {
859                             cov_mark::hit!(glob_across_crates);
860                             // glob import from other crate => we can just import everything once
861                             let item_map = m.def_map(self.db);
862                             let scope = &item_map[m.local_id].scope;
863
864                             // Module scoped macros is included
865                             let items = scope
866                                 .resolutions()
867                                 // only keep visible names...
868                                 .map(|(n, res)| {
869                                     (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
870                                 })
871                                 .filter(|(_, res)| !res.is_none())
872                                 .collect::<Vec<_>>();
873
874                             self.update(module_id, &items, vis, ImportType::Glob);
875                         } else {
876                             // glob import from same crate => we do an initial
877                             // import, and then need to propagate any further
878                             // additions
879                             let def_map;
880                             let scope = if m.block == self.def_map.block_id() {
881                                 &self.def_map[m.local_id].scope
882                             } else {
883                                 def_map = m.def_map(self.db);
884                                 &def_map[m.local_id].scope
885                             };
886
887                             // Module scoped macros is included
888                             let items = scope
889                                 .resolutions()
890                                 // only keep visible names...
891                                 .map(|(n, res)| {
892                                     (
893                                         n,
894                                         res.filter_visibility(|v| {
895                                             v.is_visible_from_def_map(
896                                                 self.db,
897                                                 &self.def_map,
898                                                 module_id,
899                                             )
900                                         }),
901                                     )
902                                 })
903                                 .filter(|(_, res)| !res.is_none())
904                                 .collect::<Vec<_>>();
905
906                             self.update(module_id, &items, vis, ImportType::Glob);
907                             // record the glob import in case we add further items
908                             let glob = self.glob_imports.entry(m.local_id).or_default();
909                             if !glob.iter().any(|(mid, _)| *mid == module_id) {
910                                 glob.push((module_id, vis));
911                             }
912                         }
913                     }
914                     Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
915                         cov_mark::hit!(glob_enum);
916                         // glob import from enum => just import all the variants
917
918                         // XXX: urgh, so this works by accident! Here, we look at
919                         // the enum data, and, in theory, this might require us to
920                         // look back at the crate_def_map, creating a cycle. For
921                         // example, `enum E { crate::some_macro!(); }`. Luckily, the
922                         // only kind of macro that is allowed inside enum is a
923                         // `cfg_macro`, and we don't need to run name resolution for
924                         // it, but this is sheer luck!
925                         let enum_data = self.db.enum_data(e);
926                         let resolutions = enum_data
927                             .variants
928                             .iter()
929                             .map(|(local_id, variant_data)| {
930                                 let name = variant_data.name.clone();
931                                 let variant = EnumVariantId { parent: e, local_id };
932                                 let res = PerNs::both(variant.into(), variant.into(), vis);
933                                 (Some(name), res)
934                             })
935                             .collect::<Vec<_>>();
936                         self.update(module_id, &resolutions, vis, ImportType::Glob);
937                     }
938                     Some(d) => {
939                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
940                     }
941                     None => {
942                         tracing::debug!("glob import {:?} didn't resolve as type", import);
943                     }
944                 }
945             }
946         }
947     }
948
949     fn update(
950         &mut self,
951         module_id: LocalModuleId,
952         resolutions: &[(Option<Name>, PerNs)],
953         vis: Visibility,
954         import_type: ImportType,
955     ) {
956         self.db.unwind_if_cancelled();
957         self.update_recursive(module_id, resolutions, vis, import_type, 0)
958     }
959
960     fn update_recursive(
961         &mut self,
962         module_id: LocalModuleId,
963         resolutions: &[(Option<Name>, PerNs)],
964         // All resolutions are imported with this visibility; the visibilities in
965         // the `PerNs` values are ignored and overwritten
966         vis: Visibility,
967         import_type: ImportType,
968         depth: usize,
969     ) {
970         if GLOB_RECURSION_LIMIT.check(depth).is_err() {
971             // prevent stack overflows (but this shouldn't be possible)
972             panic!("infinite recursion in glob imports!");
973         }
974         let mut changed = false;
975
976         for (name, res) in resolutions {
977             match name {
978                 Some(name) => {
979                     let scope = &mut self.def_map.modules[module_id].scope;
980                     changed |= scope.push_res_with_import(
981                         &mut self.from_glob_import,
982                         (module_id, name.clone()),
983                         res.with_visibility(vis),
984                         import_type,
985                     );
986                 }
987                 None => {
988                     let tr = match res.take_types() {
989                         Some(ModuleDefId::TraitId(tr)) => tr,
990                         Some(other) => {
991                             tracing::debug!("non-trait `_` import of {:?}", other);
992                             continue;
993                         }
994                         None => continue,
995                     };
996                     let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
997                     let should_update = match old_vis {
998                         None => true,
999                         Some(old_vis) => {
1000                             let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| {
1001                                 panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr);
1002                             });
1003
1004                             if max_vis == old_vis {
1005                                 false
1006                             } else {
1007                                 cov_mark::hit!(upgrade_underscore_visibility);
1008                                 true
1009                             }
1010                         }
1011                     };
1012
1013                     if should_update {
1014                         changed = true;
1015                         self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
1016                     }
1017                 }
1018             }
1019         }
1020
1021         if !changed {
1022             return;
1023         }
1024         let glob_imports = self
1025             .glob_imports
1026             .get(&module_id)
1027             .into_iter()
1028             .flat_map(|v| v.iter())
1029             .filter(|(glob_importing_module, _)| {
1030                 // we know all resolutions have the same visibility (`vis`), so we
1031                 // just need to check that once
1032                 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
1033             })
1034             .cloned()
1035             .collect::<Vec<_>>();
1036
1037         for (glob_importing_module, glob_import_vis) in glob_imports {
1038             self.update_recursive(
1039                 glob_importing_module,
1040                 resolutions,
1041                 glob_import_vis,
1042                 ImportType::Glob,
1043                 depth + 1,
1044             );
1045         }
1046     }
1047
1048     fn resolve_macros(&mut self) -> ReachedFixedPoint {
1049         let mut macros = mem::take(&mut self.unresolved_macros);
1050         let mut resolved = Vec::new();
1051         let mut push_resolved = |directive: &MacroDirective, call_id| {
1052             resolved.push((directive.module_id, directive.depth, directive.container, call_id));
1053         };
1054         let mut res = ReachedFixedPoint::Yes;
1055         macros.retain(|directive| {
1056             let resolver = |path| {
1057                 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1058                     self.db,
1059                     ResolveMode::Other,
1060                     directive.module_id,
1061                     &path,
1062                     BuiltinShadowMode::Module,
1063                 );
1064                 resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(self.db, it))
1065             };
1066
1067             match &directive.kind {
1068                 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1069                     let call_id = macro_call_as_call_id(
1070                         self.db,
1071                         ast_id,
1072                         *expand_to,
1073                         self.def_map.krate,
1074                         &resolver,
1075                         &mut |_err| (),
1076                     );
1077                     if let Ok(Ok(call_id)) = call_id {
1078                         push_resolved(directive, call_id);
1079                         res = ReachedFixedPoint::No;
1080                         return false;
1081                     }
1082                 }
1083                 MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1084                     let call_id = derive_macro_as_call_id(
1085                         self.db,
1086                         ast_id,
1087                         *derive_attr,
1088                         *derive_pos as u32,
1089                         self.def_map.krate,
1090                         &resolver,
1091                     );
1092                     if let Ok(call_id) = call_id {
1093                         self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1094                             ast_id.ast_id,
1095                             call_id,
1096                             *derive_attr,
1097                             *derive_pos,
1098                         );
1099
1100                         push_resolved(directive, call_id);
1101                         res = ReachedFixedPoint::No;
1102                         return false;
1103                     }
1104                 }
1105                 MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => {
1106                     let &AstIdWithPath { ast_id, ref path } = file_ast_id;
1107                     let file_id = ast_id.file_id;
1108
1109                     let mut recollect_without = |collector: &mut Self| {
1110                         // Remove the original directive since we resolved it.
1111                         let mod_dir = collector.mod_dirs[&directive.module_id].clone();
1112                         collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
1113
1114                         let item_tree = tree.item_tree(self.db);
1115                         ModCollector {
1116                             def_collector: collector,
1117                             macro_depth: directive.depth,
1118                             module_id: directive.module_id,
1119                             tree_id: *tree,
1120                             item_tree: &item_tree,
1121                             mod_dir,
1122                         }
1123                         .collect(&[*mod_item], directive.container);
1124                         res = ReachedFixedPoint::No;
1125                         false
1126                     };
1127
1128                     if let Some(ident) = path.as_ident() {
1129                         if let Some(helpers) = self.derive_helpers_in_scope.get(&ast_id) {
1130                             if helpers.contains(ident) {
1131                                 cov_mark::hit!(resolved_derive_helper);
1132                                 // Resolved to derive helper. Collect the item's attributes again,
1133                                 // starting after the derive helper.
1134                                 return recollect_without(self);
1135                             }
1136                         }
1137                     }
1138
1139                     let def = match resolver(path.clone()) {
1140                         Some(def) if def.is_attribute() => def,
1141                         _ => return true,
1142                     };
1143                     if matches!(
1144                         def,
1145                         MacroDefId {  kind:MacroDefKind::BuiltInAttr(expander, _),.. }
1146                         if expander.is_derive()
1147                     ) {
1148                         // Resolved to `#[derive]`
1149
1150                         let item_tree = tree.item_tree(self.db);
1151                         let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
1152                             ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
1153                             ModItem::Union(union) => item_tree[union].ast_id().upcast(),
1154                             ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
1155                             _ => {
1156                                 let diag = DefDiagnostic::invalid_derive_target(
1157                                     directive.module_id,
1158                                     ast_id,
1159                                     attr.id,
1160                                 );
1161                                 self.def_map.diagnostics.push(diag);
1162                                 return recollect_without(self);
1163                             }
1164                         };
1165                         let ast_id = ast_id.with_value(ast_adt_id);
1166
1167                         match attr.parse_path_comma_token_tree() {
1168                             Some(derive_macros) => {
1169                                 let mut len = 0;
1170                                 for (idx, path) in derive_macros.enumerate() {
1171                                     let ast_id = AstIdWithPath::new(file_id, ast_id.value, path);
1172                                     self.unresolved_macros.push(MacroDirective {
1173                                         module_id: directive.module_id,
1174                                         depth: directive.depth + 1,
1175                                         kind: MacroDirectiveKind::Derive {
1176                                             ast_id,
1177                                             derive_attr: attr.id,
1178                                             derive_pos: idx,
1179                                         },
1180                                         container: directive.container,
1181                                     });
1182                                     len = idx;
1183                                 }
1184
1185                                 // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection.
1186                                 // This is just a trick to be able to resolve the input to derives as proper paths.
1187                                 // Check the comment in [`builtin_attr_macro`].
1188                                 let call_id = attr_macro_as_call_id(
1189                                     self.db,
1190                                     file_ast_id,
1191                                     attr,
1192                                     self.def_map.krate,
1193                                     def,
1194                                     true,
1195                                 );
1196                                 self.def_map.modules[directive.module_id]
1197                                     .scope
1198                                     .init_derive_attribute(ast_id, attr.id, call_id, len + 1);
1199                             }
1200                             None => {
1201                                 let diag = DefDiagnostic::malformed_derive(
1202                                     directive.module_id,
1203                                     ast_id,
1204                                     attr.id,
1205                                 );
1206                                 self.def_map.diagnostics.push(diag);
1207                             }
1208                         }
1209
1210                         return recollect_without(self);
1211                     }
1212
1213                     if !self.db.enable_proc_attr_macros() {
1214                         return true;
1215                     }
1216
1217                     // Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
1218                     let call_id = attr_macro_as_call_id(
1219                         self.db,
1220                         file_ast_id,
1221                         attr,
1222                         self.def_map.krate,
1223                         def,
1224                         false,
1225                     );
1226                     let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
1227
1228                     // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
1229                     // due to duplicating functions into macro expansions
1230                     if matches!(
1231                         loc.def.kind,
1232                         MacroDefKind::BuiltInAttr(expander, _)
1233                         if expander.is_test() || expander.is_bench()
1234                     ) {
1235                         return recollect_without(self);
1236                     }
1237
1238                     if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
1239                         if exp.is_dummy() {
1240                             // Proc macros that cannot be expanded are treated as not
1241                             // resolved, in order to fall back later.
1242                             self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
1243                                 directive.module_id,
1244                                 loc.kind,
1245                             ));
1246
1247                             return recollect_without(self);
1248                         }
1249                     }
1250
1251                     self.def_map.modules[directive.module_id]
1252                         .scope
1253                         .add_attr_macro_invoc(ast_id, call_id);
1254
1255                     push_resolved(directive, call_id);
1256                     res = ReachedFixedPoint::No;
1257                     return false;
1258                 }
1259             }
1260
1261             true
1262         });
1263         // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1264         self.unresolved_macros.extend(macros);
1265
1266         for (module_id, depth, container, macro_call_id) in resolved {
1267             self.collect_macro_expansion(module_id, macro_call_id, depth, container);
1268         }
1269
1270         res
1271     }
1272
1273     fn collect_macro_expansion(
1274         &mut self,
1275         module_id: LocalModuleId,
1276         macro_call_id: MacroCallId,
1277         depth: usize,
1278         container: ItemContainerId,
1279     ) {
1280         if EXPANSION_DEPTH_LIMIT.check(depth).is_err() {
1281             cov_mark::hit!(macro_expansion_overflow);
1282             tracing::warn!("macro expansion is too deep");
1283             return;
1284         }
1285         let file_id = macro_call_id.as_file();
1286
1287         // First, fetch the raw expansion result for purposes of error reporting. This goes through
1288         // `macro_expand_error` to avoid depending on the full expansion result (to improve
1289         // incrementality).
1290         let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1291         let err = self.db.macro_expand_error(macro_call_id);
1292         if let Some(err) = err {
1293             let diag = match err {
1294                 hir_expand::ExpandError::UnresolvedProcMacro => {
1295                     // Missing proc macros are non-fatal, so they are handled specially.
1296                     DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
1297                 }
1298                 _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
1299             };
1300
1301             self.def_map.diagnostics.push(diag);
1302         }
1303
1304         // If we've just resolved a derive, record its helper attributes.
1305         if let MacroCallKind::Derive { ast_id, .. } = &loc.kind {
1306             if loc.def.krate != self.def_map.krate {
1307                 let def_map = self.db.crate_def_map(loc.def.krate);
1308                 if let Some(helpers) = def_map.exported_derives.get(&loc.def) {
1309                     self.derive_helpers_in_scope
1310                         .entry(ast_id.map(|it| it.upcast()))
1311                         .or_default()
1312                         .extend(helpers.iter().cloned());
1313                 }
1314             }
1315         }
1316
1317         // Then, fetch and process the item tree. This will reuse the expansion result from above.
1318         let item_tree = self.db.file_item_tree(file_id);
1319         let mod_dir = self.mod_dirs[&module_id].clone();
1320         ModCollector {
1321             def_collector: &mut *self,
1322             macro_depth: depth,
1323             tree_id: TreeId::new(file_id, None),
1324             module_id,
1325             item_tree: &item_tree,
1326             mod_dir,
1327         }
1328         .collect(item_tree.top_level_items(), container);
1329     }
1330
1331     fn finish(mut self) -> DefMap {
1332         // Emit diagnostics for all remaining unexpanded macros.
1333
1334         let _p = profile::span("DefCollector::finish");
1335
1336         for directive in &self.unresolved_macros {
1337             match &directive.kind {
1338                 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1339                     let macro_call_as_call_id = macro_call_as_call_id(
1340                         self.db,
1341                         ast_id,
1342                         *expand_to,
1343                         self.def_map.krate,
1344                         |path| {
1345                             let resolved_res = self.def_map.resolve_path_fp_with_macro(
1346                                 self.db,
1347                                 ResolveMode::Other,
1348                                 directive.module_id,
1349                                 &path,
1350                                 BuiltinShadowMode::Module,
1351                             );
1352                             resolved_res
1353                                 .resolved_def
1354                                 .take_macros()
1355                                 .map(|it| macro_id_to_def_id(self.db, it))
1356                         },
1357                         &mut |_| (),
1358                     );
1359                     if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
1360                         self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1361                             directive.module_id,
1362                             ast_id.ast_id,
1363                             path,
1364                         ));
1365                     }
1366                 }
1367                 MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
1368                     // FIXME: we might want to diagnose this too
1369                 }
1370             }
1371         }
1372
1373         // Emit diagnostics for all remaining unresolved imports.
1374
1375         // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
1376         // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
1377         // crate names. Then we emit diagnostics for unresolved imports, but only if the import
1378         // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
1379         // heuristic, but it works in practice.
1380         let mut diagnosed_extern_crates = FxHashSet::default();
1381         for directive in &self.unresolved_imports {
1382             if let ImportSource::ExternCrate(krate) = directive.import.source {
1383                 let item_tree = krate.item_tree(self.db);
1384                 let extern_crate = &item_tree[krate.value];
1385
1386                 diagnosed_extern_crates.insert(extern_crate.name.clone());
1387
1388                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
1389                     directive.module_id,
1390                     InFile::new(krate.file_id(), extern_crate.ast_id),
1391                 ));
1392             }
1393         }
1394
1395         for directive in &self.unresolved_imports {
1396             if let ImportSource::Import { id: import, use_tree } = directive.import.source {
1397                 if matches!(
1398                     (directive.import.path.segments().first(), &directive.import.path.kind),
1399                     (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
1400                 ) {
1401                     continue;
1402                 }
1403
1404                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1405                     directive.module_id,
1406                     import,
1407                     use_tree,
1408                 ));
1409             }
1410         }
1411
1412         self.def_map
1413     }
1414 }
1415
1416 /// Walks a single module, populating defs, imports and macros
1417 struct ModCollector<'a, 'b> {
1418     def_collector: &'a mut DefCollector<'b>,
1419     macro_depth: usize,
1420     module_id: LocalModuleId,
1421     tree_id: TreeId,
1422     item_tree: &'a ItemTree,
1423     mod_dir: ModDir,
1424 }
1425
1426 impl ModCollector<'_, '_> {
1427     fn collect_in_top_module(&mut self, items: &[ModItem]) {
1428         let module = self.def_collector.def_map.module_id(self.module_id);
1429         self.collect(items, module.into())
1430     }
1431
1432     fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
1433         let krate = self.def_collector.def_map.krate;
1434
1435         // Note: don't assert that inserted value is fresh: it's simply not true
1436         // for macros.
1437         self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1438
1439         // Prelude module is always considered to be `#[macro_use]`.
1440         if let Some(prelude_module) = self.def_collector.def_map.prelude {
1441             if prelude_module.krate != krate {
1442                 cov_mark::hit!(prelude_is_macro_use);
1443                 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1444             }
1445         }
1446
1447         // This should be processed eagerly instead of deferred to resolving.
1448         // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1449         // any other items.
1450         for &item in items {
1451             let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1452             if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
1453                 if let ModItem::ExternCrate(id) = item {
1454                     let import = &self.item_tree[id];
1455                     let attrs = self.item_tree.attrs(
1456                         self.def_collector.db,
1457                         krate,
1458                         ModItem::from(id).into(),
1459                     );
1460                     if attrs.by_key("macro_use").exists() {
1461                         self.def_collector.import_macros_from_extern_crate(self.module_id, import);
1462                     }
1463                 }
1464             }
1465         }
1466
1467         for &item in items {
1468             let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1469             if let Some(cfg) = attrs.cfg() {
1470                 if !self.is_cfg_enabled(&cfg) {
1471                     self.emit_unconfigured_diagnostic(item, &cfg);
1472                     continue;
1473                 }
1474             }
1475
1476             if let Err(()) = self.resolve_attributes(&attrs, item, container) {
1477                 // Do not process the item. It has at least one non-builtin attribute, so the
1478                 // fixed-point algorithm is required to resolve the rest of them.
1479                 continue;
1480             }
1481
1482             let db = self.def_collector.db;
1483             let module = self.def_collector.def_map.module_id(self.module_id);
1484             let def_map = &mut self.def_collector.def_map;
1485             let update_def =
1486                 |def_collector: &mut DefCollector, id, name: &Name, vis, has_constructor| {
1487                     def_collector.def_map.modules[self.module_id].scope.declare(id);
1488                     def_collector.update(
1489                         self.module_id,
1490                         &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1491                         vis,
1492                         ImportType::Named,
1493                     )
1494                 };
1495             let resolve_vis = |def_map: &DefMap, visibility| {
1496                 def_map
1497                     .resolve_visibility(db, self.module_id, visibility)
1498                     .unwrap_or(Visibility::Public)
1499             };
1500
1501             match item {
1502                 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
1503                 ModItem::Import(import_id) => {
1504                     let imports = Import::from_use(
1505                         db,
1506                         krate,
1507                         self.item_tree,
1508                         ItemTreeId::new(self.tree_id, import_id),
1509                     );
1510                     self.def_collector.unresolved_imports.extend(imports.into_iter().map(
1511                         |import| ImportDirective {
1512                             module_id: self.module_id,
1513                             import,
1514                             status: PartialResolvedImport::Unresolved,
1515                         },
1516                     ));
1517                 }
1518                 ModItem::ExternCrate(import_id) => {
1519                     self.def_collector.unresolved_imports.push(ImportDirective {
1520                         module_id: self.module_id,
1521                         import: Import::from_extern_crate(
1522                             db,
1523                             krate,
1524                             self.item_tree,
1525                             ItemTreeId::new(self.tree_id, import_id),
1526                         ),
1527                         status: PartialResolvedImport::Unresolved,
1528                     })
1529                 }
1530                 ModItem::ExternBlock(block) => self.collect(
1531                     &self.item_tree[block].children,
1532                     ItemContainerId::ExternBlockId(
1533                         ExternBlockLoc {
1534                             container: module,
1535                             id: ItemTreeId::new(self.tree_id, block),
1536                         }
1537                         .intern(db),
1538                     ),
1539                 ),
1540                 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
1541                 ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
1542                 ModItem::MacroDef(id) => self.collect_macro_def(id, module),
1543                 ModItem::Impl(imp) => {
1544                     let impl_id =
1545                         ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
1546                             .intern(db);
1547                     self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1548                 }
1549                 ModItem::Function(id) => {
1550                     let it = &self.item_tree[id];
1551                     let fn_id =
1552                         FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1553
1554                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1555                     if self.def_collector.is_proc_macro {
1556                         if self.module_id == def_map.root {
1557                             if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
1558                                 let crate_root = def_map.module_id(def_map.root);
1559                                 self.def_collector.export_proc_macro(
1560                                     proc_macro,
1561                                     ItemTreeId::new(self.tree_id, id),
1562                                     fn_id,
1563                                     crate_root,
1564                                 );
1565                             }
1566                         }
1567                     }
1568
1569                     update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
1570                 }
1571                 ModItem::Struct(id) => {
1572                     let it = &self.item_tree[id];
1573
1574                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1575                     update_def(
1576                         self.def_collector,
1577                         StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1578                             .intern(db)
1579                             .into(),
1580                         &it.name,
1581                         vis,
1582                         !matches!(it.fields, Fields::Record(_)),
1583                     );
1584                 }
1585                 ModItem::Union(id) => {
1586                     let it = &self.item_tree[id];
1587
1588                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1589                     update_def(
1590                         self.def_collector,
1591                         UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1592                             .intern(db)
1593                             .into(),
1594                         &it.name,
1595                         vis,
1596                         false,
1597                     );
1598                 }
1599                 ModItem::Enum(id) => {
1600                     let it = &self.item_tree[id];
1601
1602                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1603                     update_def(
1604                         self.def_collector,
1605                         EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1606                             .intern(db)
1607                             .into(),
1608                         &it.name,
1609                         vis,
1610                         false,
1611                     );
1612                 }
1613                 ModItem::Const(id) => {
1614                     let it = &self.item_tree[id];
1615                     let const_id =
1616                         ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1617
1618                     match &it.name {
1619                         Some(name) => {
1620                             let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1621                             update_def(self.def_collector, const_id.into(), name, vis, false);
1622                         }
1623                         None => {
1624                             // const _: T = ...;
1625                             self.def_collector.def_map.modules[self.module_id]
1626                                 .scope
1627                                 .define_unnamed_const(const_id);
1628                         }
1629                     }
1630                 }
1631                 ModItem::Static(id) => {
1632                     let it = &self.item_tree[id];
1633
1634                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1635                     update_def(
1636                         self.def_collector,
1637                         StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1638                             .intern(db)
1639                             .into(),
1640                         &it.name,
1641                         vis,
1642                         false,
1643                     );
1644                 }
1645                 ModItem::Trait(id) => {
1646                     let it = &self.item_tree[id];
1647
1648                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1649                     update_def(
1650                         self.def_collector,
1651                         TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1652                             .intern(db)
1653                             .into(),
1654                         &it.name,
1655                         vis,
1656                         false,
1657                     );
1658                 }
1659                 ModItem::TypeAlias(id) => {
1660                     let it = &self.item_tree[id];
1661
1662                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1663                     update_def(
1664                         self.def_collector,
1665                         TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1666                             .intern(db)
1667                             .into(),
1668                         &it.name,
1669                         vis,
1670                         false,
1671                     );
1672                 }
1673             }
1674         }
1675     }
1676
1677     fn collect_module(&mut self, module: &Mod, attrs: &Attrs) {
1678         let path_attr = attrs.by_key("path").string_value();
1679         let is_macro_use = attrs.by_key("macro_use").exists();
1680         match &module.kind {
1681             // inline module, just recurse
1682             ModKind::Inline { items } => {
1683                 let module_id = self.push_child_module(
1684                     module.name.clone(),
1685                     AstId::new(self.file_id(), module.ast_id),
1686                     None,
1687                     &self.item_tree[module.visibility],
1688                 );
1689
1690                 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1691                 {
1692                     ModCollector {
1693                         def_collector: &mut *self.def_collector,
1694                         macro_depth: self.macro_depth,
1695                         module_id,
1696                         tree_id: self.tree_id,
1697                         item_tree: self.item_tree,
1698                         mod_dir,
1699                     }
1700                     .collect_in_top_module(&*items);
1701                     if is_macro_use {
1702                         self.import_all_legacy_macros(module_id);
1703                     }
1704                 }
1705             }
1706             // out of line module, resolve, parse and recurse
1707             ModKind::Outline => {
1708                 let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
1709                 let db = self.def_collector.db;
1710                 match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
1711                 {
1712                     Ok((file_id, is_mod_rs, mod_dir)) => {
1713                         let item_tree = db.file_item_tree(file_id.into());
1714                         let krate = self.def_collector.def_map.krate;
1715                         let is_enabled = item_tree
1716                             .top_level_attrs(db, krate)
1717                             .cfg()
1718                             .map_or(true, |cfg| self.is_cfg_enabled(&cfg));
1719                         if is_enabled {
1720                             let module_id = self.push_child_module(
1721                                 module.name.clone(),
1722                                 ast_id,
1723                                 Some((file_id, is_mod_rs)),
1724                                 &self.item_tree[module.visibility],
1725                             );
1726                             ModCollector {
1727                                 def_collector: self.def_collector,
1728                                 macro_depth: self.macro_depth,
1729                                 module_id,
1730                                 tree_id: TreeId::new(file_id.into(), None),
1731                                 item_tree: &item_tree,
1732                                 mod_dir,
1733                             }
1734                             .collect_in_top_module(item_tree.top_level_items());
1735                             let is_macro_use = is_macro_use
1736                                 || item_tree
1737                                     .top_level_attrs(db, krate)
1738                                     .by_key("macro_use")
1739                                     .exists();
1740                             if is_macro_use {
1741                                 self.import_all_legacy_macros(module_id);
1742                             }
1743                         }
1744                     }
1745                     Err(candidates) => {
1746                         self.def_collector.def_map.diagnostics.push(
1747                             DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
1748                         );
1749                     }
1750                 };
1751             }
1752         }
1753     }
1754
1755     fn push_child_module(
1756         &mut self,
1757         name: Name,
1758         declaration: AstId<ast::Module>,
1759         definition: Option<(FileId, bool)>,
1760         visibility: &crate::visibility::RawVisibility,
1761     ) -> LocalModuleId {
1762         let def_map = &mut self.def_collector.def_map;
1763         let vis = def_map
1764             .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1765             .unwrap_or(Visibility::Public);
1766         let modules = &mut def_map.modules;
1767         let origin = match definition {
1768             None => ModuleOrigin::Inline { definition: declaration },
1769             Some((definition, is_mod_rs)) => {
1770                 ModuleOrigin::File { declaration, definition, is_mod_rs }
1771             }
1772         };
1773
1774         let res = modules.alloc(ModuleData::new(origin, vis));
1775         modules[res].parent = Some(self.module_id);
1776         for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
1777             modules[res].scope.define_legacy_macro(name, mac)
1778         }
1779         modules[self.module_id].children.insert(name.clone(), res);
1780
1781         let module = def_map.module_id(res);
1782         let def = ModuleDefId::from(module);
1783
1784         def_map.modules[self.module_id].scope.declare(def);
1785         self.def_collector.update(
1786             self.module_id,
1787             &[(Some(name), PerNs::from_def(def, vis, false))],
1788             vis,
1789             ImportType::Named,
1790         );
1791         res
1792     }
1793
1794     /// Resolves attributes on an item.
1795     ///
1796     /// Returns `Err` when some attributes could not be resolved to builtins and have been
1797     /// registered as unresolved.
1798     ///
1799     /// If `ignore_up_to` is `Some`, attributes preceding and including that attribute will be
1800     /// assumed to be resolved already.
1801     fn resolve_attributes(
1802         &mut self,
1803         attrs: &Attrs,
1804         mod_item: ModItem,
1805         container: ItemContainerId,
1806     ) -> Result<(), ()> {
1807         let mut ignore_up_to =
1808             self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
1809         let iter = attrs
1810             .iter()
1811             .dedup_by(|a, b| {
1812                 // FIXME: this should not be required, all attributes on an item should have a
1813                 // unique ID!
1814                 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1815                 //     #[cfg_attr(not(off), unresolved, unresolved)]
1816                 //     struct S;
1817                 // We should come up with a different way to ID attributes.
1818                 a.id == b.id
1819             })
1820             .skip_while(|attr| match ignore_up_to {
1821                 Some(id) if attr.id == id => {
1822                     ignore_up_to = None;
1823                     true
1824                 }
1825                 Some(_) => true,
1826                 None => false,
1827             });
1828
1829         for attr in iter {
1830             if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
1831                 continue;
1832             }
1833             tracing::debug!("non-builtin attribute {}", attr.path);
1834
1835             let ast_id = AstIdWithPath::new(
1836                 self.file_id(),
1837                 mod_item.ast_id(self.item_tree),
1838                 attr.path.as_ref().clone(),
1839             );
1840             self.def_collector.unresolved_macros.push(MacroDirective {
1841                 module_id: self.module_id,
1842                 depth: self.macro_depth + 1,
1843                 kind: MacroDirectiveKind::Attr {
1844                     ast_id,
1845                     attr: attr.clone(),
1846                     mod_item,
1847                     tree: self.tree_id,
1848                 },
1849                 container,
1850             });
1851
1852             return Err(());
1853         }
1854
1855         Ok(())
1856     }
1857
1858     fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>, module: ModuleId) {
1859         let krate = self.def_collector.def_map.krate;
1860         let mac = &self.item_tree[id];
1861         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1862         let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
1863
1864         let export_attr = attrs.by_key("macro_export");
1865
1866         let is_export = export_attr.exists();
1867         let local_inner = if is_export {
1868             export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
1869                 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
1870                     ident.text.contains("local_inner_macros")
1871                 }
1872                 _ => false,
1873             })
1874         } else {
1875             false
1876         };
1877
1878         // Case 1: builtin macros
1879         let expander = if attrs.by_key("rustc_builtin_macro").exists() {
1880             // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1881             let name;
1882             let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1883                 Some(it) => {
1884                     // FIXME: a hacky way to create a Name from string.
1885                     name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1886                     &name
1887                 }
1888                 None => {
1889                     let explicit_name =
1890                         attrs.by_key("rustc_builtin_macro").tt_values().next().and_then(|tt| {
1891                             match tt.token_trees.first() {
1892                                 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
1893                                 _ => None,
1894                             }
1895                         });
1896                     match explicit_name {
1897                         Some(ident) => {
1898                             name = ident.as_name();
1899                             &name
1900                         }
1901                         None => &mac.name,
1902                     }
1903                 }
1904             };
1905             match find_builtin_macro(name) {
1906                 Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
1907                 Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
1908                 None => {
1909                     self.def_collector
1910                         .def_map
1911                         .diagnostics
1912                         .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1913                     return;
1914                 }
1915             }
1916         } else {
1917             // Case 2: normal `macro_rules!` macro
1918             MacroExpander::Declarative
1919         };
1920
1921         let macro_id = MacroRulesLoc {
1922             container: module,
1923             id: ItemTreeId::new(self.tree_id, id),
1924             local_inner,
1925             expander,
1926         }
1927         .intern(self.def_collector.db);
1928         self.def_collector.define_macro_rules(
1929             self.module_id,
1930             mac.name.clone(),
1931             macro_id,
1932             is_export,
1933         );
1934     }
1935
1936     fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>, module: ModuleId) {
1937         let krate = self.def_collector.def_map.krate;
1938         let mac = &self.item_tree[id];
1939         let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
1940
1941         // Case 1: builtin macros
1942         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1943         let expander = if attrs.by_key("rustc_builtin_macro").exists() {
1944             if let Some(expander) = find_builtin_macro(&mac.name) {
1945                 match expander {
1946                     Either::Left(it) => MacroExpander::BuiltIn(it),
1947                     Either::Right(it) => MacroExpander::BuiltInEager(it),
1948                 }
1949             } else if let Some(expander) = find_builtin_derive(&mac.name) {
1950                 MacroExpander::BuiltInDerive(expander)
1951             } else if let Some(expander) = find_builtin_attr(&mac.name) {
1952                 MacroExpander::BuiltInAttr(expander)
1953             } else {
1954                 self.def_collector
1955                     .def_map
1956                     .diagnostics
1957                     .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1958                 return;
1959             }
1960         } else {
1961             // Case 2: normal `macro`
1962             MacroExpander::Declarative
1963         };
1964
1965         let macro_id =
1966             Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
1967                 .intern(self.def_collector.db);
1968         self.def_collector.define_macro_def(
1969             self.module_id,
1970             mac.name.clone(),
1971             macro_id,
1972             &self.item_tree[mac.visibility],
1973         );
1974     }
1975
1976     fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
1977         let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
1978
1979         // Case 1: try to resolve in legacy scope and expand macro_rules
1980         let mut error = None;
1981         match macro_call_as_call_id(
1982             self.def_collector.db,
1983             &ast_id,
1984             mac.expand_to,
1985             self.def_collector.def_map.krate,
1986             |path| {
1987                 path.as_ident().and_then(|name| {
1988                     self.def_collector.def_map.with_ancestor_maps(
1989                         self.def_collector.db,
1990                         self.module_id,
1991                         &mut |map, module| {
1992                             map[module]
1993                                 .scope
1994                                 .get_legacy_macro(name)
1995                                 .map(|it| macro_id_to_def_id(self.def_collector.db, it.into()))
1996                         },
1997                     )
1998                 })
1999             },
2000             &mut |err| {
2001                 error.get_or_insert(err);
2002             },
2003         ) {
2004             Ok(Ok(macro_call_id)) => {
2005                 // Legacy macros need to be expanded immediately, so that any macros they produce
2006                 // are in scope.
2007                 self.def_collector.collect_macro_expansion(
2008                     self.module_id,
2009                     macro_call_id,
2010                     self.macro_depth + 1,
2011                     container,
2012                 );
2013
2014                 if let Some(err) = error {
2015                     self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2016                         self.module_id,
2017                         MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2018                         err.to_string(),
2019                     ));
2020                 }
2021
2022                 return;
2023             }
2024             Ok(Err(_)) => {
2025                 // Built-in macro failed eager expansion.
2026
2027                 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2028                     self.module_id,
2029                     MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2030                     error.unwrap().to_string(),
2031                 ));
2032                 return;
2033             }
2034             Err(UnresolvedMacro { .. }) => (),
2035         }
2036
2037         // Case 2: resolve in module scope, expand during name resolution.
2038         self.def_collector.unresolved_macros.push(MacroDirective {
2039             module_id: self.module_id,
2040             depth: self.macro_depth + 1,
2041             kind: MacroDirectiveKind::FnLike { ast_id, expand_to: mac.expand_to },
2042             container,
2043         });
2044     }
2045
2046     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
2047         let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
2048         for (name, macro_) in macros {
2049             self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
2050         }
2051     }
2052
2053     fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
2054         self.def_collector.cfg_options.check(cfg) != Some(false)
2055     }
2056
2057     fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
2058         let ast_id = item.ast_id(self.item_tree);
2059
2060         let ast_id = InFile::new(self.file_id(), ast_id);
2061         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2062             self.module_id,
2063             ast_id,
2064             cfg.clone(),
2065             self.def_collector.cfg_options.clone(),
2066         ));
2067     }
2068
2069     fn file_id(&self) -> HirFileId {
2070         self.tree_id.file_id()
2071     }
2072 }
2073
2074 #[cfg(test)]
2075 mod tests {
2076     use crate::{db::DefDatabase, test_db::TestDB};
2077     use base_db::{fixture::WithFixture, SourceDatabase};
2078
2079     use super::*;
2080
2081     fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
2082         let mut collector = DefCollector {
2083             db,
2084             def_map,
2085             deps: FxHashMap::default(),
2086             glob_imports: FxHashMap::default(),
2087             unresolved_imports: Vec::new(),
2088             resolved_imports: Vec::new(),
2089             unresolved_macros: Vec::new(),
2090             mod_dirs: FxHashMap::default(),
2091             cfg_options: &CfgOptions::default(),
2092             proc_macros: Default::default(),
2093             from_glob_import: Default::default(),
2094             skip_attrs: Default::default(),
2095             derive_helpers_in_scope: Default::default(),
2096             is_proc_macro: false,
2097         };
2098         collector.seed_with_top_level();
2099         collector.collect();
2100         collector.def_map
2101     }
2102
2103     fn do_resolve(not_ra_fixture: &str) -> DefMap {
2104         let (db, file_id) = TestDB::with_single_file(not_ra_fixture);
2105         let krate = db.test_crate();
2106
2107         let edition = db.crate_graph()[krate].edition;
2108         let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
2109         let def_map = DefMap::empty(krate, edition, module_origin);
2110         do_collect_defs(&db, def_map)
2111     }
2112
2113     #[test]
2114     fn test_macro_expand_will_stop_1() {
2115         do_resolve(
2116             r#"
2117 macro_rules! foo {
2118     ($($ty:ty)*) => { foo!($($ty)*); }
2119 }
2120 foo!(KABOOM);
2121 "#,
2122         );
2123         do_resolve(
2124             r#"
2125 macro_rules! foo {
2126     ($($ty:ty)*) => { foo!(() $($ty)*); }
2127 }
2128 foo!(KABOOM);
2129 "#,
2130         );
2131     }
2132
2133     #[ignore]
2134     #[test]
2135     fn test_macro_expand_will_stop_2() {
2136         // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2137         // the release mode. That's why the argument is not an ra_fixture --
2138         // otherwise injection highlighting gets stuck.
2139         //
2140         // We need to find a way to fail this faster.
2141         do_resolve(
2142             r#"
2143 macro_rules! foo {
2144     ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2145 }
2146 foo!(KABOOM);
2147 "#,
2148         );
2149     }
2150 }