]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/nameres/collector.rs
2c8f1b5b8b691deb96c1cff57bd1390e616c1a12
[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;
7
8 use base_db::{CrateId, FileId, ProcMacroId};
9 use cfg::{CfgExpr, CfgOptions};
10 use hir_expand::{
11     ast_id_map::FileAstId,
12     builtin_derive::find_builtin_derive,
13     builtin_macro::find_builtin_macro,
14     name::{AsName, Name},
15     proc_macro::ProcMacroExpander,
16     FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17 };
18 use hir_expand::{InFile, MacroCallLoc};
19 use rustc_hash::{FxHashMap, FxHashSet};
20 use syntax::ast;
21
22 use crate::{
23     attr::{AttrId, Attrs},
24     builtin_attr,
25     db::DefDatabase,
26     derive_macro_as_call_id,
27     intern::Interned,
28     item_scope::{ImportType, PerNsGlobImports},
29     item_tree::{
30         self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem,
31         ModKind, StructDefKind,
32     },
33     macro_call_as_call_id,
34     nameres::{
35         diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
36         BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
37     },
38     path::{ImportAlias, ModPath, PathKind},
39     per_ns::PerNs,
40     visibility::{RawVisibility, Visibility},
41     AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
42     LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
43     UnresolvedMacro,
44 };
45
46 use super::proc_macro::{ProcMacroDef, ProcMacroKind};
47
48 const GLOB_RECURSION_LIMIT: usize = 100;
49 const EXPANSION_DEPTH_LIMIT: usize = 128;
50 const FIXED_POINT_LIMIT: usize = 8192;
51
52 pub(super) fn collect_defs(
53     db: &dyn DefDatabase,
54     mut def_map: DefMap,
55     block: Option<AstId<ast::BlockExpr>>,
56 ) -> DefMap {
57     let crate_graph = db.crate_graph();
58
59     if block.is_none() {
60         // populate external prelude
61         for dep in &crate_graph[def_map.krate].dependencies {
62             log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
63             let dep_def_map = db.crate_def_map(dep.crate_id);
64             def_map
65                 .extern_prelude
66                 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
67
68             // look for the prelude
69             // If the dependency defines a prelude, we overwrite an already defined
70             // prelude. This is necessary to import the "std" prelude if a crate
71             // depends on both "core" and "std".
72             if dep_def_map.prelude.is_some() {
73                 def_map.prelude = dep_def_map.prelude;
74             }
75         }
76     }
77
78     let cfg_options = &crate_graph[def_map.krate].cfg_options;
79     let proc_macros = &crate_graph[def_map.krate].proc_macro;
80     let proc_macros = proc_macros
81         .iter()
82         .enumerate()
83         .map(|(idx, it)| {
84             // FIXME: a hacky way to create a Name from string.
85             let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
86             (name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx as u32)))
87         })
88         .collect();
89
90     let mut collector = DefCollector {
91         db,
92         def_map,
93         glob_imports: FxHashMap::default(),
94         unresolved_imports: Vec::new(),
95         resolved_imports: Vec::new(),
96
97         unresolved_macros: Vec::new(),
98         mod_dirs: FxHashMap::default(),
99         cfg_options,
100         proc_macros,
101         exports_proc_macros: false,
102         from_glob_import: Default::default(),
103         ignore_attrs_on: FxHashSet::default(),
104         derive_helpers_in_scope: FxHashMap::default(),
105     };
106     match block {
107         Some(block) => {
108             collector.seed_with_inner(block);
109         }
110         None => {
111             collector.seed_with_top_level();
112         }
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 is came 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) => *ns,
135             PartialResolvedImport::Resolved(ns) => *ns,
136         }
137     }
138 }
139
140 #[derive(Clone, Debug, Eq, PartialEq)]
141 enum ImportSource {
142     Import(ItemTreeId<item_tree::Import>),
143     ExternCrate(ItemTreeId<item_tree::ExternCrate>),
144 }
145
146 #[derive(Clone, Debug, Eq, PartialEq)]
147 struct Import {
148     path: Interned<ModPath>,
149     alias: Option<ImportAlias>,
150     visibility: RawVisibility,
151     is_glob: bool,
152     is_prelude: bool,
153     is_extern_crate: bool,
154     is_macro_use: bool,
155     source: ImportSource,
156 }
157
158 impl Import {
159     fn from_use(
160         db: &dyn DefDatabase,
161         krate: CrateId,
162         tree: &ItemTree,
163         id: ItemTreeId<item_tree::Import>,
164     ) -> Self {
165         let it = &tree[id.value];
166         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
167         let visibility = &tree[it.visibility];
168         Self {
169             path: it.path.clone(),
170             alias: it.alias.clone(),
171             visibility: visibility.clone(),
172             is_glob: it.is_glob,
173             is_prelude: attrs.by_key("prelude_import").exists(),
174             is_extern_crate: false,
175             is_macro_use: false,
176             source: ImportSource::Import(id),
177         }
178     }
179
180     fn from_extern_crate(
181         db: &dyn DefDatabase,
182         krate: CrateId,
183         tree: &ItemTree,
184         id: ItemTreeId<item_tree::ExternCrate>,
185     ) -> Self {
186         let it = &tree[id.value];
187         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
188         let visibility = &tree[it.visibility];
189         Self {
190             path: Interned::new(ModPath::from_segments(
191                 PathKind::Plain,
192                 iter::once(it.name.clone()),
193             )),
194             alias: it.alias.clone(),
195             visibility: visibility.clone(),
196             is_glob: false,
197             is_prelude: false,
198             is_extern_crate: true,
199             is_macro_use: attrs.by_key("macro_use").exists(),
200             source: ImportSource::ExternCrate(id),
201         }
202     }
203 }
204
205 #[derive(Clone, Debug, Eq, PartialEq)]
206 struct ImportDirective {
207     module_id: LocalModuleId,
208     import: Import,
209     status: PartialResolvedImport,
210 }
211
212 #[derive(Clone, Debug, Eq, PartialEq)]
213 struct MacroDirective {
214     module_id: LocalModuleId,
215     depth: usize,
216     kind: MacroDirectiveKind,
217 }
218
219 #[derive(Clone, Debug, Eq, PartialEq)]
220 enum MacroDirectiveKind {
221     FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
222     Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
223     Attr { ast_id: AstIdWithPath<ast::Item>, attr: AttrId, mod_item: ModItem },
224 }
225
226 struct DefData<'a> {
227     id: ModuleDefId,
228     name: &'a Name,
229     visibility: &'a RawVisibility,
230     has_constructor: bool,
231 }
232
233 /// Walks the tree of module recursively
234 struct DefCollector<'a> {
235     db: &'a dyn DefDatabase,
236     def_map: DefMap,
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     exports_proc_macros: bool,
249     from_glob_import: PerNsGlobImports,
250     ignore_attrs_on: FxHashSet<InFile<ModItem>>,
251     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
252     /// attributes.
253     derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
254 }
255
256 impl DefCollector<'_> {
257     fn seed_with_top_level(&mut self) {
258         let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
259         let item_tree = self.db.file_item_tree(file_id.into());
260         let module_id = self.def_map.root;
261         self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
262         if item_tree
263             .top_level_attrs(self.db, self.def_map.krate)
264             .cfg()
265             .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
266         {
267             ModCollector {
268                 def_collector: &mut *self,
269                 macro_depth: 0,
270                 module_id,
271                 file_id: file_id.into(),
272                 item_tree: &item_tree,
273                 mod_dir: ModDir::root(),
274             }
275             .collect(item_tree.top_level_items());
276         }
277     }
278
279     fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) {
280         let item_tree = self.db.file_item_tree(block.file_id);
281         let module_id = self.def_map.root;
282         self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block };
283         if item_tree
284             .top_level_attrs(self.db, self.def_map.krate)
285             .cfg()
286             .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
287         {
288             ModCollector {
289                 def_collector: &mut *self,
290                 macro_depth: 0,
291                 module_id,
292                 file_id: block.file_id,
293                 item_tree: &item_tree,
294                 mod_dir: ModDir::root(),
295             }
296             .collect(item_tree.inner_items_of_block(block.value));
297         }
298     }
299
300     fn collect(&mut self) {
301         // main name resolution fixed-point loop.
302         let mut i = 0;
303         'outer: loop {
304             loop {
305                 self.db.check_canceled();
306                 loop {
307                     if self.resolve_imports() == ReachedFixedPoint::Yes {
308                         break;
309                     }
310                 }
311                 if self.resolve_macros() == ReachedFixedPoint::Yes {
312                     break;
313                 }
314
315                 i += 1;
316                 if i == FIXED_POINT_LIMIT {
317                     log::error!("name resolution is stuck");
318                     break 'outer;
319                 }
320             }
321
322             if self.reseed_with_unresolved_attributes() == ReachedFixedPoint::Yes {
323                 break;
324             }
325         }
326
327         // Resolve all indeterminate resolved imports again
328         // As some of the macros will expand newly import shadowing partial resolved imports
329         // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
330         // correctly
331         let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
332             if let PartialResolvedImport::Indeterminate(_) = directive.status {
333                 let mut directive = directive.clone();
334                 directive.status = PartialResolvedImport::Unresolved;
335                 Some(directive)
336             } else {
337                 None
338             }
339         });
340         self.unresolved_imports.extend(partial_resolved);
341         self.resolve_imports();
342
343         let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
344         // show unresolved imports in completion, etc
345         for directive in &unresolved_imports {
346             self.record_resolved_import(directive)
347         }
348         self.unresolved_imports = unresolved_imports;
349
350         // FIXME: This condition should instead check if this is a `proc-macro` type crate.
351         if self.exports_proc_macros {
352             // A crate exporting procedural macros is not allowed to export anything else.
353             //
354             // Additionally, while the proc macro entry points must be `pub`, they are not publicly
355             // exported in type/value namespace. This function reduces the visibility of all items
356             // in the crate root that aren't proc macros.
357             let root = self.def_map.root;
358             let module_id = self.def_map.module_id(root);
359             let root = &mut self.def_map.modules[root];
360             root.scope.censor_non_proc_macros(module_id);
361         }
362     }
363
364     /// When the fixed-point loop reaches a stable state, we might still have some unresolved
365     /// attributes (or unexpanded attribute proc macros) left over. This takes them, and feeds the
366     /// item they're applied to back into name resolution.
367     ///
368     /// This effectively ignores the fact that the macro is there and just treats the items as
369     /// normal code.
370     ///
371     /// This improves UX when proc macros are turned off or don't work, and replicates the behavior
372     /// before we supported proc. attribute macros.
373     fn reseed_with_unresolved_attributes(&mut self) -> ReachedFixedPoint {
374         cov_mark::hit!(unresolved_attribute_fallback);
375
376         let mut added_items = false;
377         let unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
378         for directive in &unresolved_macros {
379             if let MacroDirectiveKind::Attr { ast_id, mod_item, .. } = &directive.kind {
380                 // Make sure to only add such items once.
381                 if !self.ignore_attrs_on.insert(ast_id.ast_id.with_value(*mod_item)) {
382                     continue;
383                 }
384
385                 let file_id = self.def_map[directive.module_id].definition_source(self.db).file_id;
386                 let item_tree = self.db.file_item_tree(file_id);
387                 let mod_dir = self.mod_dirs[&directive.module_id].clone();
388                 ModCollector {
389                     def_collector: &mut *self,
390                     macro_depth: directive.depth,
391                     module_id: directive.module_id,
392                     file_id,
393                     item_tree: &item_tree,
394                     mod_dir,
395                 }
396                 .collect(&[*mod_item]);
397                 added_items = true;
398             }
399         }
400
401         // The collection above might add new unresolved macros (eg. derives), so merge the lists.
402         self.unresolved_macros.extend(unresolved_macros);
403
404         if added_items {
405             // Continue name resolution with the new data.
406             ReachedFixedPoint::No
407         } else {
408             ReachedFixedPoint::Yes
409         }
410     }
411
412     /// Adds a definition of procedural macro `name` to the root module.
413     ///
414     /// # Notes on procedural macro resolution
415     ///
416     /// Procedural macro functionality is provided by the build system: It has to build the proc
417     /// macro and pass the resulting dynamic library to rust-analyzer.
418     ///
419     /// When procedural macro support is enabled, the list of proc macros exported by a crate is
420     /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
421     /// derived from the dynamic library.
422     ///
423     /// However, we *also* would like to be able to at least *resolve* macros on our own, without
424     /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
425     /// use a dummy expander that always errors. This comes with the drawback of macros potentially
426     /// going out of sync with what the build system sees (since we resolve using VFS state, but
427     /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
428     fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
429         self.exports_proc_macros = true;
430         let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
431             Some((_, expander)) => MacroDefId {
432                 krate: self.def_map.krate,
433                 kind: MacroDefKind::ProcMacro(*expander, ast_id),
434                 local_inner: false,
435             },
436             None => MacroDefId {
437                 krate: self.def_map.krate,
438                 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate), ast_id),
439                 local_inner: false,
440             },
441         };
442
443         self.define_proc_macro(def.name.clone(), macro_def);
444         self.def_map.exported_proc_macros.insert(macro_def, def);
445     }
446
447     /// Define a macro with `macro_rules`.
448     ///
449     /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
450     /// then it is also defined in the root module scope.
451     /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
452     ///
453     /// It is surprising that the macro will never be in the current module scope.
454     /// These code fails with "unresolved import/macro",
455     /// ```rust,compile_fail
456     /// mod m { macro_rules! foo { () => {} } }
457     /// use m::foo as bar;
458     /// ```
459     ///
460     /// ```rust,compile_fail
461     /// macro_rules! foo { () => {} }
462     /// self::foo!();
463     /// crate::foo!();
464     /// ```
465     ///
466     /// Well, this code compiles, because the plain path `foo` in `use` is searched
467     /// in the legacy textual scope only.
468     /// ```rust
469     /// macro_rules! foo { () => {} }
470     /// use foo as bar;
471     /// ```
472     fn define_macro_rules(
473         &mut self,
474         module_id: LocalModuleId,
475         name: Name,
476         macro_: MacroDefId,
477         export: bool,
478     ) {
479         // Textual scoping
480         self.define_legacy_macro(module_id, name.clone(), macro_);
481
482         // Module scoping
483         // In Rust, `#[macro_export]` macros are unconditionally visible at the
484         // crate root, even if the parent modules is **not** visible.
485         if export {
486             self.update(
487                 self.def_map.root,
488                 &[(Some(name), PerNs::macros(macro_, Visibility::Public))],
489                 Visibility::Public,
490                 ImportType::Named,
491             );
492         }
493     }
494
495     /// Define a legacy textual scoped macro in module
496     ///
497     /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
498     /// It will clone all macros from parent legacy scope, whose definition is prior to
499     /// the definition of current module.
500     /// And also, `macro_use` on a module will import all legacy macros visible inside to
501     /// current legacy scope, with possible shadowing.
502     fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
503         // Always shadowing
504         self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
505     }
506
507     /// Define a macro 2.0 macro
508     ///
509     /// The scoped of macro 2.0 macro is equal to normal function
510     fn define_macro_def(
511         &mut self,
512         module_id: LocalModuleId,
513         name: Name,
514         macro_: MacroDefId,
515         vis: &RawVisibility,
516     ) {
517         let vis =
518             self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
519         self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named);
520     }
521
522     /// Define a proc macro
523     ///
524     /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
525     /// And unconditionally exported.
526     fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) {
527         self.update(
528             self.def_map.root,
529             &[(Some(name), PerNs::macros(macro_, Visibility::Public))],
530             Visibility::Public,
531             ImportType::Named,
532         );
533     }
534
535     /// Import macros from `#[macro_use] extern crate`.
536     fn import_macros_from_extern_crate(
537         &mut self,
538         current_module_id: LocalModuleId,
539         extern_crate: &item_tree::ExternCrate,
540     ) {
541         log::debug!(
542             "importing macros from extern crate: {:?} ({:?})",
543             extern_crate,
544             self.def_map.edition,
545         );
546
547         let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
548
549         if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
550             if m == self.def_map.module_id(current_module_id) {
551                 cov_mark::hit!(ignore_macro_use_extern_crate_self);
552                 return;
553             }
554
555             cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
556             self.import_all_macros_exported(current_module_id, m.krate);
557         }
558     }
559
560     /// Import all exported macros from another crate
561     ///
562     /// Exported macros are just all macros in the root module scope.
563     /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
564     /// created by `use` in the root module, ignoring the visibility of `use`.
565     fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
566         let def_map = self.db.crate_def_map(krate);
567         for (name, def) in def_map[def_map.root].scope.macros() {
568             // `macro_use` only bring things into legacy scope.
569             self.define_legacy_macro(current_module_id, name.clone(), def);
570         }
571     }
572
573     /// Tries to resolve every currently unresolved import.
574     fn resolve_imports(&mut self) -> ReachedFixedPoint {
575         let mut res = ReachedFixedPoint::Yes;
576         let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
577         let imports = imports
578             .into_iter()
579             .filter_map(|mut directive| {
580                 directive.status = self.resolve_import(directive.module_id, &directive.import);
581                 match directive.status {
582                     PartialResolvedImport::Indeterminate(_) => {
583                         self.record_resolved_import(&directive);
584                         // FIXME: For avoid performance regression,
585                         // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
586                         self.resolved_imports.push(directive);
587                         res = ReachedFixedPoint::No;
588                         None
589                     }
590                     PartialResolvedImport::Resolved(_) => {
591                         self.record_resolved_import(&directive);
592                         self.resolved_imports.push(directive);
593                         res = ReachedFixedPoint::No;
594                         None
595                     }
596                     PartialResolvedImport::Unresolved => Some(directive),
597                 }
598             })
599             .collect();
600         self.unresolved_imports = imports;
601         res
602     }
603
604     fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
605         log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
606         if import.is_extern_crate {
607             let res = self.def_map.resolve_name_in_extern_prelude(
608                 self.db,
609                 &import
610                     .path
611                     .as_ident()
612                     .expect("extern crate should have been desugared to one-element path"),
613             );
614             if res.is_none() {
615                 PartialResolvedImport::Unresolved
616             } else {
617                 PartialResolvedImport::Resolved(res)
618             }
619         } else {
620             let res = self.def_map.resolve_path_fp_with_macro(
621                 self.db,
622                 ResolveMode::Import,
623                 module_id,
624                 &import.path,
625                 BuiltinShadowMode::Module,
626             );
627
628             let def = res.resolved_def;
629             if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
630                 return PartialResolvedImport::Unresolved;
631             }
632
633             if let Some(krate) = res.krate {
634                 if krate != self.def_map.krate {
635                     return PartialResolvedImport::Resolved(def);
636                 }
637             }
638
639             // Check whether all namespace is resolved
640             if def.take_types().is_some()
641                 && def.take_values().is_some()
642                 && def.take_macros().is_some()
643             {
644                 PartialResolvedImport::Resolved(def)
645             } else {
646                 PartialResolvedImport::Indeterminate(def)
647             }
648         }
649     }
650
651     fn record_resolved_import(&mut self, directive: &ImportDirective) {
652         let module_id = directive.module_id;
653         let import = &directive.import;
654         let def = directive.status.namespaces();
655         let vis = self
656             .def_map
657             .resolve_visibility(self.db, module_id, &directive.import.visibility)
658             .unwrap_or(Visibility::Public);
659
660         if import.is_glob {
661             log::debug!("glob import: {:?}", import);
662             match def.take_types() {
663                 Some(ModuleDefId::ModuleId(m)) => {
664                     if import.is_prelude {
665                         cov_mark::hit!(std_prelude);
666                         self.def_map.prelude = Some(m);
667                     } else if m.krate != self.def_map.krate {
668                         cov_mark::hit!(glob_across_crates);
669                         // glob import from other crate => we can just import everything once
670                         let item_map = m.def_map(self.db);
671                         let scope = &item_map[m.local_id].scope;
672
673                         // Module scoped macros is included
674                         let items = scope
675                             .resolutions()
676                             // only keep visible names...
677                             .map(|(n, res)| {
678                                 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
679                             })
680                             .filter(|(_, res)| !res.is_none())
681                             .collect::<Vec<_>>();
682
683                         self.update(module_id, &items, vis, ImportType::Glob);
684                     } else {
685                         // glob import from same crate => we do an initial
686                         // import, and then need to propagate any further
687                         // additions
688                         let def_map;
689                         let scope = if m.block == self.def_map.block_id() {
690                             &self.def_map[m.local_id].scope
691                         } else {
692                             def_map = m.def_map(self.db);
693                             &def_map[m.local_id].scope
694                         };
695
696                         // Module scoped macros is included
697                         let items = scope
698                             .resolutions()
699                             // only keep visible names...
700                             .map(|(n, res)| {
701                                 (
702                                     n,
703                                     res.filter_visibility(|v| {
704                                         v.is_visible_from_def_map(self.db, &self.def_map, module_id)
705                                     }),
706                                 )
707                             })
708                             .filter(|(_, res)| !res.is_none())
709                             .collect::<Vec<_>>();
710
711                         self.update(module_id, &items, vis, ImportType::Glob);
712                         // record the glob import in case we add further items
713                         let glob = self.glob_imports.entry(m.local_id).or_default();
714                         if !glob.iter().any(|(mid, _)| *mid == module_id) {
715                             glob.push((module_id, vis));
716                         }
717                     }
718                 }
719                 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
720                     cov_mark::hit!(glob_enum);
721                     // glob import from enum => just import all the variants
722
723                     // XXX: urgh, so this works by accident! Here, we look at
724                     // the enum data, and, in theory, this might require us to
725                     // look back at the crate_def_map, creating a cycle. For
726                     // example, `enum E { crate::some_macro!(); }`. Luckily, the
727                     // only kind of macro that is allowed inside enum is a
728                     // `cfg_macro`, and we don't need to run name resolution for
729                     // it, but this is sheer luck!
730                     let enum_data = self.db.enum_data(e);
731                     let resolutions = enum_data
732                         .variants
733                         .iter()
734                         .map(|(local_id, variant_data)| {
735                             let name = variant_data.name.clone();
736                             let variant = EnumVariantId { parent: e, local_id };
737                             let res = PerNs::both(variant.into(), variant.into(), vis);
738                             (Some(name), res)
739                         })
740                         .collect::<Vec<_>>();
741                     self.update(module_id, &resolutions, vis, ImportType::Glob);
742                 }
743                 Some(d) => {
744                     log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
745                 }
746                 None => {
747                     log::debug!("glob import {:?} didn't resolve as type", import);
748                 }
749             }
750         } else {
751             let name = match &import.alias {
752                 Some(ImportAlias::Alias(name)) => Some(name.clone()),
753                 Some(ImportAlias::Underscore) => None,
754                 None => match import.path.segments().last() {
755                     Some(last_segment) => Some(last_segment.clone()),
756                     None => {
757                         cov_mark::hit!(bogus_paths);
758                         return;
759                     }
760                 },
761             };
762
763             log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
764
765             // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
766             if import.is_extern_crate && module_id == self.def_map.root {
767                 if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) {
768                     self.def_map.extern_prelude.insert(name.clone(), def);
769                 }
770             }
771
772             self.update(module_id, &[(name, def)], vis, ImportType::Named);
773         }
774     }
775
776     fn update(
777         &mut self,
778         module_id: LocalModuleId,
779         resolutions: &[(Option<Name>, PerNs)],
780         vis: Visibility,
781         import_type: ImportType,
782     ) {
783         self.db.check_canceled();
784         self.update_recursive(module_id, resolutions, vis, import_type, 0)
785     }
786
787     fn update_recursive(
788         &mut self,
789         module_id: LocalModuleId,
790         resolutions: &[(Option<Name>, PerNs)],
791         // All resolutions are imported with this visibility; the visibilities in
792         // the `PerNs` values are ignored and overwritten
793         vis: Visibility,
794         import_type: ImportType,
795         depth: usize,
796     ) {
797         if depth > GLOB_RECURSION_LIMIT {
798             // prevent stack overflows (but this shouldn't be possible)
799             panic!("infinite recursion in glob imports!");
800         }
801         let mut changed = false;
802
803         for (name, res) in resolutions {
804             match name {
805                 Some(name) => {
806                     let scope = &mut self.def_map.modules[module_id].scope;
807                     changed |= scope.push_res_with_import(
808                         &mut self.from_glob_import,
809                         (module_id, name.clone()),
810                         res.with_visibility(vis),
811                         import_type,
812                     );
813                 }
814                 None => {
815                     let tr = match res.take_types() {
816                         Some(ModuleDefId::TraitId(tr)) => tr,
817                         Some(other) => {
818                             log::debug!("non-trait `_` import of {:?}", other);
819                             continue;
820                         }
821                         None => continue,
822                     };
823                     let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
824                     let should_update = match old_vis {
825                         None => true,
826                         Some(old_vis) => {
827                             let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| {
828                                 panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr);
829                             });
830
831                             if max_vis == old_vis {
832                                 false
833                             } else {
834                                 cov_mark::hit!(upgrade_underscore_visibility);
835                                 true
836                             }
837                         }
838                     };
839
840                     if should_update {
841                         changed = true;
842                         self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
843                     }
844                 }
845             }
846         }
847
848         if !changed {
849             return;
850         }
851         let glob_imports = self
852             .glob_imports
853             .get(&module_id)
854             .into_iter()
855             .flat_map(|v| v.iter())
856             .filter(|(glob_importing_module, _)| {
857                 // we know all resolutions have the same visibility (`vis`), so we
858                 // just need to check that once
859                 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
860             })
861             .cloned()
862             .collect::<Vec<_>>();
863
864         for (glob_importing_module, glob_import_vis) in glob_imports {
865             self.update_recursive(
866                 glob_importing_module,
867                 resolutions,
868                 glob_import_vis,
869                 ImportType::Glob,
870                 depth + 1,
871             );
872         }
873     }
874
875     fn resolve_macros(&mut self) -> ReachedFixedPoint {
876         let mut macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
877         let mut resolved = Vec::new();
878         let mut res = ReachedFixedPoint::Yes;
879         macros.retain(|directive| {
880             let resolver = |path| {
881                 let resolved_res = self.def_map.resolve_path_fp_with_macro(
882                     self.db,
883                     ResolveMode::Other,
884                     directive.module_id,
885                     &path,
886                     BuiltinShadowMode::Module,
887                 );
888                 resolved_res.resolved_def.take_macros()
889             };
890
891             match &directive.kind {
892                 MacroDirectiveKind::FnLike { ast_id, fragment } => {
893                     match macro_call_as_call_id(
894                         ast_id,
895                         *fragment,
896                         self.db,
897                         self.def_map.krate,
898                         &resolver,
899                         &mut |_err| (),
900                     ) {
901                         Ok(Ok(call_id)) => {
902                             resolved.push((directive.module_id, call_id, directive.depth));
903                             res = ReachedFixedPoint::No;
904                             return false;
905                         }
906                         Err(UnresolvedMacro { .. }) | Ok(Err(_)) => {}
907                     }
908                 }
909                 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
910                     match derive_macro_as_call_id(
911                         ast_id,
912                         *derive_attr,
913                         self.db,
914                         self.def_map.krate,
915                         &resolver,
916                     ) {
917                         Ok(call_id) => {
918                             resolved.push((directive.module_id, call_id, directive.depth));
919                             res = ReachedFixedPoint::No;
920                             return false;
921                         }
922                         Err(UnresolvedMacro { .. }) => (),
923                     }
924                 }
925                 MacroDirectiveKind::Attr { .. } => {
926                     // not yet :)
927                 }
928             }
929
930             true
931         });
932         self.unresolved_macros = macros;
933
934         for (module_id, macro_call_id, depth) in resolved {
935             self.collect_macro_expansion(module_id, macro_call_id, depth);
936         }
937
938         res
939     }
940
941     fn collect_macro_expansion(
942         &mut self,
943         module_id: LocalModuleId,
944         macro_call_id: MacroCallId,
945         depth: usize,
946     ) {
947         if depth > EXPANSION_DEPTH_LIMIT {
948             cov_mark::hit!(macro_expansion_overflow);
949             log::warn!("macro expansion is too deep");
950             return;
951         }
952         let file_id = macro_call_id.as_file();
953
954         // First, fetch the raw expansion result for purposes of error reporting. This goes through
955         // `macro_expand_error` to avoid depending on the full expansion result (to improve
956         // incrementality).
957         let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
958         let err = self.db.macro_expand_error(macro_call_id);
959         if let Some(err) = err {
960             let diag = match err {
961                 hir_expand::ExpandError::UnresolvedProcMacro => {
962                     // Missing proc macros are non-fatal, so they are handled specially.
963                     DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
964                 }
965                 _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
966             };
967
968             self.def_map.diagnostics.push(diag);
969         }
970
971         // If we've just resolved a derive, record its helper attributes.
972         if let MacroCallKind::Derive { ast_id, .. } = &loc.kind {
973             if loc.def.krate != self.def_map.krate {
974                 let def_map = self.db.crate_def_map(loc.def.krate);
975                 if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
976                     if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
977                         self.derive_helpers_in_scope
978                             .entry(*ast_id)
979                             .or_default()
980                             .extend(helpers.iter().cloned());
981                     }
982                 }
983             }
984         }
985
986         // Then, fetch and process the item tree. This will reuse the expansion result from above.
987         let item_tree = self.db.file_item_tree(file_id);
988         let mod_dir = self.mod_dirs[&module_id].clone();
989         ModCollector {
990             def_collector: &mut *self,
991             macro_depth: depth,
992             file_id,
993             module_id,
994             item_tree: &item_tree,
995             mod_dir,
996         }
997         .collect(item_tree.top_level_items());
998     }
999
1000     fn finish(mut self) -> DefMap {
1001         // Emit diagnostics for all remaining unexpanded macros.
1002
1003         for directive in &self.unresolved_macros {
1004             match &directive.kind {
1005                 MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
1006                     ast_id,
1007                     *fragment,
1008                     self.db,
1009                     self.def_map.krate,
1010                     |path| {
1011                         let resolved_res = self.def_map.resolve_path_fp_with_macro(
1012                             self.db,
1013                             ResolveMode::Other,
1014                             directive.module_id,
1015                             &path,
1016                             BuiltinShadowMode::Module,
1017                         );
1018                         resolved_res.resolved_def.take_macros()
1019                     },
1020                     &mut |_| (),
1021                 ) {
1022                     Ok(_) => (),
1023                     Err(UnresolvedMacro { path }) => {
1024                         self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1025                             directive.module_id,
1026                             ast_id.ast_id,
1027                             path,
1028                         ));
1029                     }
1030                 },
1031                 MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
1032                     // FIXME: we might want to diagnose this too
1033                 }
1034             }
1035         }
1036
1037         // Emit diagnostics for all remaining unresolved imports.
1038
1039         // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
1040         // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
1041         // crate names. Then we emit diagnostics for unresolved imports, but only if the import
1042         // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
1043         // heuristic, but it works in practice.
1044         let mut diagnosed_extern_crates = FxHashSet::default();
1045         for directive in &self.unresolved_imports {
1046             if let ImportSource::ExternCrate(krate) = directive.import.source {
1047                 let item_tree = krate.item_tree(self.db);
1048                 let extern_crate = &item_tree[krate.value];
1049
1050                 diagnosed_extern_crates.insert(extern_crate.name.clone());
1051
1052                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
1053                     directive.module_id,
1054                     InFile::new(krate.file_id(), extern_crate.ast_id),
1055                 ));
1056             }
1057         }
1058
1059         for directive in &self.unresolved_imports {
1060             if let ImportSource::Import(import) = &directive.import.source {
1061                 let item_tree = import.item_tree(self.db);
1062                 let import_data = &item_tree[import.value];
1063
1064                 match (import_data.path.segments().first(), &import_data.path.kind) {
1065                     (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
1066                         if diagnosed_extern_crates.contains(krate) {
1067                             continue;
1068                         }
1069                     }
1070                     _ => {}
1071                 }
1072
1073                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1074                     directive.module_id,
1075                     InFile::new(import.file_id(), import_data.ast_id),
1076                     import_data.index,
1077                 ));
1078             }
1079         }
1080
1081         self.def_map
1082     }
1083 }
1084
1085 /// Walks a single module, populating defs, imports and macros
1086 struct ModCollector<'a, 'b> {
1087     def_collector: &'a mut DefCollector<'b>,
1088     macro_depth: usize,
1089     module_id: LocalModuleId,
1090     file_id: HirFileId,
1091     item_tree: &'a ItemTree,
1092     mod_dir: ModDir,
1093 }
1094
1095 impl ModCollector<'_, '_> {
1096     fn collect(&mut self, items: &[ModItem]) {
1097         let krate = self.def_collector.def_map.krate;
1098
1099         // Note: don't assert that inserted value is fresh: it's simply not true
1100         // for macros.
1101         self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1102
1103         // Prelude module is always considered to be `#[macro_use]`.
1104         if let Some(prelude_module) = self.def_collector.def_map.prelude {
1105             if prelude_module.krate != self.def_collector.def_map.krate {
1106                 cov_mark::hit!(prelude_is_macro_use);
1107                 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1108             }
1109         }
1110
1111         // This should be processed eagerly instead of deferred to resolving.
1112         // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1113         // any other items.
1114         for item in items {
1115             let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
1116             if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
1117                 if let ModItem::ExternCrate(id) = item {
1118                     let import = self.item_tree[*id].clone();
1119                     let attrs = self.item_tree.attrs(
1120                         self.def_collector.db,
1121                         krate,
1122                         ModItem::from(*id).into(),
1123                     );
1124                     if attrs.by_key("macro_use").exists() {
1125                         self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
1126                     }
1127                 }
1128             }
1129         }
1130
1131         for &item in items {
1132             let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1133             if let Some(cfg) = attrs.cfg() {
1134                 if !self.is_cfg_enabled(&cfg) {
1135                     self.emit_unconfigured_diagnostic(item, &cfg);
1136                     continue;
1137                 }
1138             }
1139
1140             if let Err(()) = self.resolve_attributes(&attrs, None, item) {
1141                 // Do not process the item. It has at least one non-builtin attribute, so the
1142                 // fixed-point algorithm is required to resolve the rest of them.
1143                 continue;
1144             }
1145
1146             let module = self.def_collector.def_map.module_id(self.module_id);
1147
1148             let mut def = None;
1149             match item {
1150                 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
1151                 ModItem::Import(import_id) => {
1152                     self.def_collector.unresolved_imports.push(ImportDirective {
1153                         module_id: self.module_id,
1154                         import: Import::from_use(
1155                             self.def_collector.db,
1156                             krate,
1157                             &self.item_tree,
1158                             ItemTreeId::new(self.file_id, import_id),
1159                         ),
1160                         status: PartialResolvedImport::Unresolved,
1161                     })
1162                 }
1163                 ModItem::ExternCrate(import_id) => {
1164                     self.def_collector.unresolved_imports.push(ImportDirective {
1165                         module_id: self.module_id,
1166                         import: Import::from_extern_crate(
1167                             self.def_collector.db,
1168                             krate,
1169                             &self.item_tree,
1170                             ItemTreeId::new(self.file_id, import_id),
1171                         ),
1172                         status: PartialResolvedImport::Unresolved,
1173                     })
1174                 }
1175                 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
1176                 ModItem::MacroRules(id) => self.collect_macro_rules(id),
1177                 ModItem::MacroDef(id) => self.collect_macro_def(id),
1178                 ModItem::Impl(imp) => {
1179                     let module = self.def_collector.def_map.module_id(self.module_id);
1180                     let impl_id =
1181                         ImplLoc { container: module, id: ItemTreeId::new(self.file_id, imp) }
1182                             .intern(self.def_collector.db);
1183                     self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1184                 }
1185                 ModItem::Function(id) => {
1186                     let func = &self.item_tree[id];
1187
1188                     let ast_id = InFile::new(self.file_id, func.ast_id);
1189                     self.collect_proc_macro_def(&func.name, ast_id, &attrs);
1190
1191                     def = Some(DefData {
1192                         id: FunctionLoc {
1193                             container: module.into(),
1194                             id: ItemTreeId::new(self.file_id, id),
1195                         }
1196                         .intern(self.def_collector.db)
1197                         .into(),
1198                         name: &func.name,
1199                         visibility: &self.item_tree[func.visibility],
1200                         has_constructor: false,
1201                     });
1202                 }
1203                 ModItem::Struct(id) => {
1204                     let it = &self.item_tree[id];
1205
1206                     // FIXME: check attrs to see if this is an attribute macro invocation;
1207                     // in which case we don't add the invocation, just a single attribute
1208                     // macro invocation
1209                     self.collect_derives(&attrs, it.ast_id.upcast());
1210
1211                     def = Some(DefData {
1212                         id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1213                             .intern(self.def_collector.db)
1214                             .into(),
1215                         name: &it.name,
1216                         visibility: &self.item_tree[it.visibility],
1217                         has_constructor: it.kind != StructDefKind::Record,
1218                     });
1219                 }
1220                 ModItem::Union(id) => {
1221                     let it = &self.item_tree[id];
1222
1223                     // FIXME: check attrs to see if this is an attribute macro invocation;
1224                     // in which case we don't add the invocation, just a single attribute
1225                     // macro invocation
1226                     self.collect_derives(&attrs, it.ast_id.upcast());
1227
1228                     def = Some(DefData {
1229                         id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1230                             .intern(self.def_collector.db)
1231                             .into(),
1232                         name: &it.name,
1233                         visibility: &self.item_tree[it.visibility],
1234                         has_constructor: false,
1235                     });
1236                 }
1237                 ModItem::Enum(id) => {
1238                     let it = &self.item_tree[id];
1239
1240                     // FIXME: check attrs to see if this is an attribute macro invocation;
1241                     // in which case we don't add the invocation, just a single attribute
1242                     // macro invocation
1243                     self.collect_derives(&attrs, it.ast_id.upcast());
1244
1245                     def = Some(DefData {
1246                         id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1247                             .intern(self.def_collector.db)
1248                             .into(),
1249                         name: &it.name,
1250                         visibility: &self.item_tree[it.visibility],
1251                         has_constructor: false,
1252                     });
1253                 }
1254                 ModItem::Const(id) => {
1255                     let it = &self.item_tree[id];
1256                     let const_id = ConstLoc {
1257                         container: module.into(),
1258                         id: ItemTreeId::new(self.file_id, id),
1259                     }
1260                     .intern(self.def_collector.db);
1261
1262                     match &it.name {
1263                         Some(name) => {
1264                             def = Some(DefData {
1265                                 id: const_id.into(),
1266                                 name,
1267                                 visibility: &self.item_tree[it.visibility],
1268                                 has_constructor: false,
1269                             });
1270                         }
1271                         None => {
1272                             // const _: T = ...;
1273                             self.def_collector.def_map.modules[self.module_id]
1274                                 .scope
1275                                 .define_unnamed_const(const_id);
1276                         }
1277                     }
1278                 }
1279                 ModItem::Static(id) => {
1280                     let it = &self.item_tree[id];
1281
1282                     def = Some(DefData {
1283                         id: StaticLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1284                             .intern(self.def_collector.db)
1285                             .into(),
1286                         name: &it.name,
1287                         visibility: &self.item_tree[it.visibility],
1288                         has_constructor: false,
1289                     });
1290                 }
1291                 ModItem::Trait(id) => {
1292                     let it = &self.item_tree[id];
1293
1294                     def = Some(DefData {
1295                         id: TraitLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1296                             .intern(self.def_collector.db)
1297                             .into(),
1298                         name: &it.name,
1299                         visibility: &self.item_tree[it.visibility],
1300                         has_constructor: false,
1301                     });
1302                 }
1303                 ModItem::TypeAlias(id) => {
1304                     let it = &self.item_tree[id];
1305
1306                     def = Some(DefData {
1307                         id: TypeAliasLoc {
1308                             container: module.into(),
1309                             id: ItemTreeId::new(self.file_id, id),
1310                         }
1311                         .intern(self.def_collector.db)
1312                         .into(),
1313                         name: &it.name,
1314                         visibility: &self.item_tree[it.visibility],
1315                         has_constructor: false,
1316                     });
1317                 }
1318             }
1319
1320             if let Some(DefData { id, name, visibility, has_constructor }) = def {
1321                 self.def_collector.def_map.modules[self.module_id].scope.define_def(id);
1322                 let vis = self
1323                     .def_collector
1324                     .def_map
1325                     .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1326                     .unwrap_or(Visibility::Public);
1327                 self.def_collector.update(
1328                     self.module_id,
1329                     &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1330                     vis,
1331                     ImportType::Named,
1332                 )
1333             }
1334         }
1335     }
1336
1337     fn collect_module(&mut self, module: &Mod, attrs: &Attrs) {
1338         let path_attr = attrs.by_key("path").string_value();
1339         let is_macro_use = attrs.by_key("macro_use").exists();
1340         match &module.kind {
1341             // inline module, just recurse
1342             ModKind::Inline { items } => {
1343                 let module_id = self.push_child_module(
1344                     module.name.clone(),
1345                     AstId::new(self.file_id, module.ast_id),
1346                     None,
1347                     &self.item_tree[module.visibility],
1348                 );
1349
1350                 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1351                 {
1352                     ModCollector {
1353                         def_collector: &mut *self.def_collector,
1354                         macro_depth: self.macro_depth,
1355                         module_id,
1356                         file_id: self.file_id,
1357                         item_tree: self.item_tree,
1358                         mod_dir,
1359                     }
1360                     .collect(&*items);
1361                     if is_macro_use {
1362                         self.import_all_legacy_macros(module_id);
1363                     }
1364                 }
1365             }
1366             // out of line module, resolve, parse and recurse
1367             ModKind::Outline {} => {
1368                 let ast_id = AstId::new(self.file_id, module.ast_id);
1369                 let db = self.def_collector.db;
1370                 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) {
1371                     Ok((file_id, is_mod_rs, mod_dir)) => {
1372                         let item_tree = db.file_item_tree(file_id.into());
1373                         if item_tree
1374                             .top_level_attrs(db, self.def_collector.def_map.krate)
1375                             .cfg()
1376                             .map_or(true, |cfg| {
1377                                 self.def_collector.cfg_options.check(&cfg) != Some(false)
1378                             })
1379                         {
1380                             let module_id = self.push_child_module(
1381                                 module.name.clone(),
1382                                 ast_id,
1383                                 Some((file_id, is_mod_rs)),
1384                                 &self.item_tree[module.visibility],
1385                             );
1386                             ModCollector {
1387                                 def_collector: &mut *self.def_collector,
1388                                 macro_depth: self.macro_depth,
1389                                 module_id,
1390                                 file_id: file_id.into(),
1391                                 item_tree: &item_tree,
1392                                 mod_dir,
1393                             }
1394                             .collect(item_tree.top_level_items());
1395                             if is_macro_use
1396                                 || item_tree
1397                                     .top_level_attrs(db, self.def_collector.def_map.krate)
1398                                     .by_key("macro_use")
1399                                     .exists()
1400                             {
1401                                 self.import_all_legacy_macros(module_id);
1402                             }
1403                         }
1404                     }
1405                     Err(candidate) => {
1406                         self.def_collector.def_map.diagnostics.push(
1407                             DefDiagnostic::unresolved_module(self.module_id, ast_id, candidate),
1408                         );
1409                     }
1410                 };
1411             }
1412         }
1413     }
1414
1415     fn push_child_module(
1416         &mut self,
1417         name: Name,
1418         declaration: AstId<ast::Module>,
1419         definition: Option<(FileId, bool)>,
1420         visibility: &crate::visibility::RawVisibility,
1421     ) -> LocalModuleId {
1422         let vis = self
1423             .def_collector
1424             .def_map
1425             .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1426             .unwrap_or(Visibility::Public);
1427         let modules = &mut self.def_collector.def_map.modules;
1428         let res = modules.alloc(ModuleData::default());
1429         modules[res].parent = Some(self.module_id);
1430         modules[res].origin = match definition {
1431             None => ModuleOrigin::Inline { definition: declaration },
1432             Some((definition, is_mod_rs)) => {
1433                 ModuleOrigin::File { declaration, definition, is_mod_rs }
1434             }
1435         };
1436         for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
1437             modules[res].scope.define_legacy_macro(name, mac)
1438         }
1439         modules[self.module_id].children.insert(name.clone(), res);
1440         let module = self.def_collector.def_map.module_id(res);
1441         let def: ModuleDefId = module.into();
1442         self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1443         self.def_collector.update(
1444             self.module_id,
1445             &[(Some(name), PerNs::from_def(def, vis, false))],
1446             vis,
1447             ImportType::Named,
1448         );
1449         res
1450     }
1451
1452     /// Resolves attributes on an item.
1453     ///
1454     /// Returns `Err` when some attributes could not be resolved to builtins and have been
1455     /// registered as unresolved.
1456     fn resolve_attributes(
1457         &mut self,
1458         attrs: &Attrs,
1459         mut ignore_up_to: Option<AttrId>,
1460         mod_item: ModItem,
1461     ) -> Result<(), ()> {
1462         fn is_builtin_attr(path: &ModPath) -> bool {
1463             if path.kind == PathKind::Plain {
1464                 if let Some(tool_module) = path.segments().first() {
1465                     let tool_module = tool_module.to_string();
1466                     if builtin_attr::TOOL_MODULES.iter().any(|m| tool_module == *m) {
1467                         return true;
1468                     }
1469                 }
1470
1471                 if let Some(name) = path.as_ident() {
1472                     let name = name.to_string();
1473                     if builtin_attr::INERT_ATTRIBUTES
1474                         .iter()
1475                         .chain(builtin_attr::EXTRA_ATTRIBUTES)
1476                         .any(|attr| name == *attr)
1477                     {
1478                         return true;
1479                     }
1480                 }
1481             }
1482
1483             false
1484         }
1485
1486         // We failed to resolve an attribute on this item earlier, and are falling back to treating
1487         // the item as-is.
1488         if self.def_collector.ignore_attrs_on.contains(&InFile::new(self.file_id, mod_item)) {
1489             return Ok(());
1490         }
1491
1492         match attrs
1493             .iter()
1494             .skip_while(|attr| match ignore_up_to {
1495                 Some(id) if attr.id == id => {
1496                     ignore_up_to = None;
1497                     false
1498                 }
1499                 Some(_) => true,
1500                 None => false,
1501             })
1502             .find(|attr| !is_builtin_attr(&attr.path))
1503         {
1504             Some(non_builtin_attr) => {
1505                 log::debug!("non-builtin attribute {}", non_builtin_attr.path);
1506
1507                 let ast_id = AstIdWithPath::new(
1508                     self.file_id,
1509                     mod_item.ast_id(self.item_tree),
1510                     non_builtin_attr.path.as_ref().clone(),
1511                 );
1512                 self.def_collector.unresolved_macros.push(MacroDirective {
1513                     module_id: self.module_id,
1514                     depth: self.macro_depth + 1,
1515                     kind: MacroDirectiveKind::Attr { ast_id, attr: non_builtin_attr.id, mod_item },
1516                 });
1517
1518                 Err(())
1519             }
1520             None => Ok(()),
1521         }
1522     }
1523
1524     fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) {
1525         for derive in attrs.by_key("derive").attrs() {
1526             match derive.parse_derive() {
1527                 Some(derive_macros) => {
1528                     for path in derive_macros {
1529                         let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1530                         self.def_collector.unresolved_macros.push(MacroDirective {
1531                             module_id: self.module_id,
1532                             depth: self.macro_depth + 1,
1533                             kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id },
1534                         });
1535                     }
1536                 }
1537                 None => {
1538                     // FIXME: diagnose
1539                     log::debug!("malformed derive: {:?}", derive);
1540                 }
1541             }
1542         }
1543     }
1544
1545     /// If `attrs` registers a procedural macro, collects its definition.
1546     fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
1547         // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
1548         if let Some(proc_macro) = attrs.parse_proc_macro_decl(func_name) {
1549             self.def_collector.export_proc_macro(proc_macro, ast_id);
1550         }
1551     }
1552
1553     fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
1554         let krate = self.def_collector.def_map.krate;
1555         let mac = &self.item_tree[id];
1556         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1557         let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1558
1559         let export_attr = attrs.by_key("macro_export");
1560
1561         let is_export = export_attr.exists();
1562         let is_local_inner = if is_export {
1563             export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
1564                 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
1565                     ident.text.contains("local_inner_macros")
1566                 }
1567                 _ => false,
1568             })
1569         } else {
1570             false
1571         };
1572
1573         // Case 1: builtin macros
1574         if attrs.by_key("rustc_builtin_macro").exists() {
1575             // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1576             let name;
1577             let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1578                 Some(it) => {
1579                     // FIXME: a hacky way to create a Name from string.
1580                     name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1581                     &name
1582                 }
1583                 None => &mac.name,
1584             };
1585             let krate = self.def_collector.def_map.krate;
1586             if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
1587                 self.def_collector.define_macro_rules(
1588                     self.module_id,
1589                     mac.name.clone(),
1590                     macro_id,
1591                     is_export,
1592                 );
1593                 return;
1594             }
1595         }
1596
1597         // Case 2: normal `macro_rules!` macro
1598         let macro_id = MacroDefId {
1599             krate: self.def_collector.def_map.krate,
1600             kind: MacroDefKind::Declarative(ast_id),
1601             local_inner: is_local_inner,
1602         };
1603         self.def_collector.define_macro_rules(
1604             self.module_id,
1605             mac.name.clone(),
1606             macro_id,
1607             is_export,
1608         );
1609     }
1610
1611     fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>) {
1612         let krate = self.def_collector.def_map.krate;
1613         let mac = &self.item_tree[id];
1614         let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1615
1616         // Case 1: bulitin macros
1617         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1618         if attrs.by_key("rustc_builtin_macro").exists() {
1619             let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1620                 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
1621
1622             if let Some(macro_id) = macro_id {
1623                 self.def_collector.define_macro_def(
1624                     self.module_id,
1625                     mac.name.clone(),
1626                     macro_id,
1627                     &self.item_tree[mac.visibility],
1628                 );
1629             }
1630             return;
1631         }
1632
1633         // Case 2: normal `macro`
1634         let macro_id = MacroDefId {
1635             krate: self.def_collector.def_map.krate,
1636             kind: MacroDefKind::Declarative(ast_id),
1637             local_inner: false,
1638         };
1639
1640         self.def_collector.define_macro_def(
1641             self.module_id,
1642             mac.name.clone(),
1643             macro_id,
1644             &self.item_tree[mac.visibility],
1645         );
1646     }
1647
1648     fn collect_macro_call(&mut self, mac: &MacroCall) {
1649         let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone());
1650
1651         // Case 1: try to resolve in legacy scope and expand macro_rules
1652         let mut error = None;
1653         match macro_call_as_call_id(
1654             &ast_id,
1655             mac.fragment,
1656             self.def_collector.db,
1657             self.def_collector.def_map.krate,
1658             |path| {
1659                 path.as_ident().and_then(|name| {
1660                     self.def_collector.def_map.with_ancestor_maps(
1661                         self.def_collector.db,
1662                         self.module_id,
1663                         &mut |map, module| map[module].scope.get_legacy_macro(&name),
1664                     )
1665                 })
1666             },
1667             &mut |err| {
1668                 error.get_or_insert(err);
1669             },
1670         ) {
1671             Ok(Ok(macro_call_id)) => {
1672                 // Legacy macros need to be expanded immediately, so that any macros they produce
1673                 // are in scope.
1674                 self.def_collector.collect_macro_expansion(
1675                     self.module_id,
1676                     macro_call_id,
1677                     self.macro_depth + 1,
1678                 );
1679
1680                 return;
1681             }
1682             Ok(Err(_)) => {
1683                 // Built-in macro failed eager expansion.
1684
1685                 // FIXME: don't parse the file here
1686                 let fragment = hir_expand::to_fragment_kind(
1687                     &ast_id.ast_id.to_node(self.def_collector.db.upcast()),
1688                 );
1689                 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1690                     self.module_id,
1691                     MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
1692                     error.unwrap().to_string(),
1693                 ));
1694                 return;
1695             }
1696             Err(UnresolvedMacro { .. }) => (),
1697         }
1698
1699         // Case 2: resolve in module scope, expand during name resolution.
1700         // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
1701         if ast_id.path.is_ident() {
1702             ast_id.path.kind = PathKind::Super(0);
1703         }
1704
1705         self.def_collector.unresolved_macros.push(MacroDirective {
1706             module_id: self.module_id,
1707             depth: self.macro_depth + 1,
1708             kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
1709         });
1710     }
1711
1712     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
1713         let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
1714         for (name, macro_) in macros {
1715             self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
1716         }
1717     }
1718
1719     fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
1720         self.def_collector.cfg_options.check(cfg) != Some(false)
1721     }
1722
1723     fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
1724         let ast_id = item.ast_id(self.item_tree);
1725
1726         let ast_id = InFile::new(self.file_id, ast_id);
1727         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
1728             self.module_id,
1729             ast_id,
1730             cfg.clone(),
1731             self.def_collector.cfg_options.clone(),
1732         ));
1733     }
1734 }
1735
1736 #[cfg(test)]
1737 mod tests {
1738     use crate::{db::DefDatabase, test_db::TestDB};
1739     use base_db::{fixture::WithFixture, SourceDatabase};
1740
1741     use super::*;
1742
1743     fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
1744         let mut collector = DefCollector {
1745             db,
1746             def_map,
1747             glob_imports: FxHashMap::default(),
1748             unresolved_imports: Vec::new(),
1749             resolved_imports: Vec::new(),
1750             unresolved_macros: Vec::new(),
1751             mod_dirs: FxHashMap::default(),
1752             cfg_options: &CfgOptions::default(),
1753             proc_macros: Default::default(),
1754             exports_proc_macros: false,
1755             from_glob_import: Default::default(),
1756             ignore_attrs_on: FxHashSet::default(),
1757             derive_helpers_in_scope: FxHashMap::default(),
1758         };
1759         collector.seed_with_top_level();
1760         collector.collect();
1761         collector.def_map
1762     }
1763
1764     fn do_resolve(code: &str) -> DefMap {
1765         let (db, _file_id) = TestDB::with_single_file(&code);
1766         let krate = db.test_crate();
1767
1768         let edition = db.crate_graph()[krate].edition;
1769         let def_map = DefMap::empty(krate, edition);
1770         do_collect_defs(&db, def_map)
1771     }
1772
1773     #[test]
1774     fn test_macro_expand_will_stop_1() {
1775         do_resolve(
1776             r#"
1777         macro_rules! foo {
1778             ($($ty:ty)*) => { foo!($($ty)*); }
1779         }
1780         foo!(KABOOM);
1781         "#,
1782         );
1783     }
1784
1785     #[ignore] // this test does succeed, but takes quite a while :/
1786     #[test]
1787     fn test_macro_expand_will_stop_2() {
1788         do_resolve(
1789             r#"
1790         macro_rules! foo {
1791             ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
1792         }
1793         foo!(KABOOM);
1794         "#,
1795         );
1796     }
1797 }