1 //! The core of the module-level name resolution algorithm.
3 //! `DefCollector::collect` contains the fixed-point iteration loop which
4 //! resolves imports and expands macros.
8 use base_db::{CrateId, Edition, FileId, ProcMacroId};
9 use cfg::{CfgExpr, CfgOptions};
11 ast_id_map::FileAstId,
12 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name},
15 proc_macro::ProcMacroExpander,
16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
18 use hir_expand::{InFile, MacroCallLoc};
19 use itertools::Itertools;
21 use rustc_hash::{FxHashMap, FxHashSet};
25 attr::{Attr, AttrId, AttrInput, Attrs},
26 attr_macro_as_call_id, builtin_attr,
28 derive_macro_as_call_id,
30 item_scope::{ImportType, PerNsGlobImports},
32 self, Fields, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod,
35 macro_call_as_call_id,
37 diagnostics::DefDiagnostic,
38 mod_resolution::ModDir,
39 path_resolution::ReachedFixedPoint,
40 proc_macro::{ProcMacroDef, ProcMacroKind},
41 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
43 path::{ImportAlias, ModPath, PathKind},
45 visibility::{RawVisibility, Visibility},
46 AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
47 LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
51 const GLOB_RECURSION_LIMIT: usize = 100;
52 const EXPANSION_DEPTH_LIMIT: usize = 128;
53 const FIXED_POINT_LIMIT: usize = 8192;
55 pub(super) fn collect_defs(
58 block: Option<AstId<ast::BlockExpr>>,
60 let crate_graph = db.crate_graph();
63 // populate external prelude
64 for dep in &crate_graph[def_map.krate].dependencies {
65 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
66 let dep_def_map = db.crate_def_map(dep.crate_id);
69 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
73 let cfg_options = &crate_graph[def_map.krate].cfg_options;
74 let proc_macros = &crate_graph[def_map.krate].proc_macro;
75 let proc_macros = proc_macros
79 // FIXME: a hacky way to create a Name from string.
80 let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
81 (name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx as u32)))
85 let mut collector = DefCollector {
88 glob_imports: FxHashMap::default(),
89 unresolved_imports: Vec::new(),
90 resolved_imports: Vec::new(),
92 unresolved_macros: Vec::new(),
93 mod_dirs: FxHashMap::default(),
96 exports_proc_macros: false,
97 from_glob_import: Default::default(),
98 skip_attrs: Default::default(),
99 derive_helpers_in_scope: Default::default(),
100 registered_attrs: Default::default(),
101 registered_tools: Default::default(),
105 collector.seed_with_inner(block);
108 collector.seed_with_top_level();
112 let mut def_map = collector.finish();
113 def_map.shrink_to_fit();
117 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
118 enum PartialResolvedImport {
119 /// None of any namespaces is resolved
121 /// One of namespaces is resolved
122 Indeterminate(PerNs),
123 /// All namespaces are resolved, OR it is came from other crate
127 impl PartialResolvedImport {
128 fn namespaces(&self) -> PerNs {
130 PartialResolvedImport::Unresolved => PerNs::none(),
131 PartialResolvedImport::Indeterminate(ns) => *ns,
132 PartialResolvedImport::Resolved(ns) => *ns,
137 #[derive(Clone, Debug, Eq, PartialEq)]
139 Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> },
140 ExternCrate(ItemTreeId<item_tree::ExternCrate>),
143 #[derive(Clone, Debug, Eq, PartialEq)]
145 path: Interned<ModPath>,
146 alias: Option<ImportAlias>,
147 visibility: RawVisibility,
150 is_extern_crate: bool,
152 source: ImportSource,
157 db: &dyn DefDatabase,
160 id: ItemTreeId<item_tree::Import>,
162 let it = &tree[id.value];
163 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
164 let visibility = &tree[it.visibility];
165 let is_prelude = attrs.by_key("prelude_import").exists();
167 let mut res = Vec::new();
168 it.use_tree.expand(|idx, path, is_glob, alias| {
170 path: Interned::new(path), // FIXME this makes little sense
172 visibility: visibility.clone(),
175 is_extern_crate: false,
177 source: ImportSource::Import { id, use_tree: idx },
183 fn from_extern_crate(
184 db: &dyn DefDatabase,
187 id: ItemTreeId<item_tree::ExternCrate>,
189 let it = &tree[id.value];
190 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
191 let visibility = &tree[it.visibility];
193 path: Interned::new(ModPath::from_segments(
195 iter::once(it.name.clone()),
197 alias: it.alias.clone(),
198 visibility: visibility.clone(),
201 is_extern_crate: true,
202 is_macro_use: attrs.by_key("macro_use").exists(),
203 source: ImportSource::ExternCrate(id),
208 #[derive(Clone, Debug, Eq, PartialEq)]
209 struct ImportDirective {
210 module_id: LocalModuleId,
212 status: PartialResolvedImport,
215 #[derive(Clone, Debug, Eq, PartialEq)]
216 struct MacroDirective {
217 module_id: LocalModuleId,
219 kind: MacroDirectiveKind,
222 #[derive(Clone, Debug, Eq, PartialEq)]
223 enum MacroDirectiveKind {
224 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
225 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
226 Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
232 visibility: &'a RawVisibility,
233 has_constructor: bool,
236 /// Walks the tree of module recursively
237 struct DefCollector<'a> {
238 db: &'a dyn DefDatabase,
240 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
241 unresolved_imports: Vec<ImportDirective>,
242 resolved_imports: Vec<ImportDirective>,
243 unresolved_macros: Vec<MacroDirective>,
244 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
245 cfg_options: &'a CfgOptions,
246 /// List of procedural macros defined by this crate. This is read from the dynamic library
247 /// built by the build system, and is the list of proc. macros we can actually expand. It is
248 /// empty when proc. macro support is disabled (in which case we still do name resolution for
250 proc_macros: Vec<(Name, ProcMacroExpander)>,
251 exports_proc_macros: bool,
252 from_glob_import: PerNsGlobImports,
253 /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
254 /// This map is used to skip all attributes up to and including the one that failed to resolve,
255 /// in order to not expand them twice.
257 /// This also stores the attributes to skip when we resolve derive helpers and non-macro
258 /// non-builtin attributes in general.
259 skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
260 /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
262 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
263 /// Custom attributes registered with `#![register_attr]`.
264 registered_attrs: Vec<String>,
265 /// Custom tool modules registered with `#![register_tool]`.
266 registered_tools: Vec<String>,
269 impl DefCollector<'_> {
270 fn seed_with_top_level(&mut self) {
271 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
272 let item_tree = self.db.file_item_tree(file_id.into());
273 let module_id = self.def_map.root;
274 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
276 let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
277 if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
278 self.inject_prelude(&attrs);
280 // Process other crate-level attributes.
281 for attr in &*attrs {
282 let attr_name = match attr.path.as_ident() {
287 let registered_name = if *attr_name == hir_expand::name![register_attr]
288 || *attr_name == hir_expand::name![register_tool]
290 match attr.input.as_deref() {
291 Some(AttrInput::TokenTree(subtree)) => match &*subtree.token_trees {
292 [tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(),
301 if *attr_name == hir_expand::name![register_attr] {
302 self.registered_attrs.push(registered_name.to_string());
303 cov_mark::hit!(register_attr);
305 self.registered_tools.push(registered_name.to_string());
306 cov_mark::hit!(register_tool);
311 def_collector: &mut *self,
314 file_id: file_id.into(),
315 item_tree: &item_tree,
316 mod_dir: ModDir::root(),
318 .collect(item_tree.top_level_items());
322 fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) {
323 let item_tree = self.db.file_item_tree(block.file_id);
324 let module_id = self.def_map.root;
325 self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block };
327 .top_level_attrs(self.db, self.def_map.krate)
329 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
332 def_collector: &mut *self,
335 file_id: block.file_id,
336 item_tree: &item_tree,
337 mod_dir: ModDir::root(),
339 .collect(item_tree.inner_items_of_block(block.value));
343 fn collect(&mut self) {
344 // main name resolution fixed-point loop.
348 self.db.unwind_if_cancelled();
350 if self.resolve_imports() == ReachedFixedPoint::Yes {
354 if self.resolve_macros() == ReachedFixedPoint::Yes {
359 if i == FIXED_POINT_LIMIT {
360 log::error!("name resolution is stuck");
365 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
370 // Resolve all indeterminate resolved imports again
371 // As some of the macros will expand newly import shadowing partial resolved imports
372 // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
374 let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
375 if let PartialResolvedImport::Indeterminate(_) = directive.status {
376 let mut directive = directive.clone();
377 directive.status = PartialResolvedImport::Unresolved;
383 self.unresolved_imports.extend(partial_resolved);
384 self.resolve_imports();
386 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
387 // show unresolved imports in completion, etc
388 for directive in &unresolved_imports {
389 self.record_resolved_import(directive)
391 self.unresolved_imports = unresolved_imports;
393 // FIXME: This condition should instead check if this is a `proc-macro` type crate.
394 if self.exports_proc_macros {
395 // A crate exporting procedural macros is not allowed to export anything else.
397 // Additionally, while the proc macro entry points must be `pub`, they are not publicly
398 // exported in type/value namespace. This function reduces the visibility of all items
399 // in the crate root that aren't proc macros.
400 let root = self.def_map.root;
401 let module_id = self.def_map.module_id(root);
402 let root = &mut self.def_map.modules[root];
403 root.scope.censor_non_proc_macros(module_id);
407 /// When the fixed-point loop reaches a stable state, we might still have some unresolved
408 /// attributes (or unexpanded attribute proc macros) left over. This takes one of them, and
409 /// feeds the item it's applied to back into name resolution.
411 /// This effectively ignores the fact that the macro is there and just treats the items as
414 /// This improves UX when proc macros are turned off or don't work, and replicates the behavior
415 /// before we supported proc. attribute macros.
416 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
417 cov_mark::hit!(unresolved_attribute_fallback);
419 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
420 let pos = unresolved_macros.iter().position(|directive| {
421 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind {
422 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
424 let file_id = ast_id.ast_id.file_id;
425 let item_tree = self.db.file_item_tree(file_id);
426 let mod_dir = self.mod_dirs[&directive.module_id].clone();
428 def_collector: &mut *self,
429 macro_depth: directive.depth,
430 module_id: directive.module_id,
432 item_tree: &item_tree,
435 .collect(&[*mod_item]);
442 if let Some(pos) = pos {
443 unresolved_macros.remove(pos);
446 // The collection above might add new unresolved macros (eg. derives), so merge the lists.
447 self.unresolved_macros.extend(unresolved_macros);
450 // Continue name resolution with the new data.
451 ReachedFixedPoint::No
453 ReachedFixedPoint::Yes
457 fn inject_prelude(&mut self, crate_attrs: &Attrs) {
458 // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
460 if crate_attrs.by_key("no_core").exists() {
461 // libcore does not get a prelude.
465 let krate = if crate_attrs.by_key("no_std").exists() {
468 let std = name![std];
469 if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
472 // If `std` does not exist for some reason, fall back to core. This mostly helps
473 // keep r-a's own tests minimal.
478 let edition = match self.def_map.edition {
479 Edition::Edition2015 => name![rust_2015],
480 Edition::Edition2018 => name![rust_2018],
481 Edition::Edition2021 => name![rust_2021],
484 let path_kind = if self.def_map.edition == Edition::Edition2015 {
489 let path = ModPath::from_segments(
491 [krate.clone(), name![prelude], edition].iter().cloned(),
493 // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
494 // FIXME remove this fallback
496 ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].iter().cloned());
498 for path in &[path, fallback_path] {
499 let (per_ns, _) = self.def_map.resolve_path(
503 BuiltinShadowMode::Other,
506 match &per_ns.types {
507 Some((ModuleDefId::ModuleId(m), _)) => {
508 self.def_map.prelude = Some(*m);
513 "could not resolve prelude path `{}` to module (resolved to {:?})",
522 /// Adds a definition of procedural macro `name` to the root module.
524 /// # Notes on procedural macro resolution
526 /// Procedural macro functionality is provided by the build system: It has to build the proc
527 /// macro and pass the resulting dynamic library to rust-analyzer.
529 /// When procedural macro support is enabled, the list of proc macros exported by a crate is
530 /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
531 /// derived from the dynamic library.
533 /// However, we *also* would like to be able to at least *resolve* macros on our own, without
534 /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
535 /// use a dummy expander that always errors. This comes with the drawback of macros potentially
536 /// going out of sync with what the build system sees (since we resolve using VFS state, but
537 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
538 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
539 let kind = def.kind.to_basedb_kind();
540 self.exports_proc_macros = true;
541 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
542 Some((_, expander)) => MacroDefId {
543 krate: self.def_map.krate,
544 kind: MacroDefKind::ProcMacro(*expander, kind, ast_id),
548 krate: self.def_map.krate,
549 kind: MacroDefKind::ProcMacro(
550 ProcMacroExpander::dummy(self.def_map.krate),
558 self.define_proc_macro(def.name.clone(), macro_def);
559 self.def_map.exported_proc_macros.insert(macro_def, def);
562 /// Define a macro with `macro_rules`.
564 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
565 /// then it is also defined in the root module scope.
566 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
568 /// It is surprising that the macro will never be in the current module scope.
569 /// These code fails with "unresolved import/macro",
570 /// ```rust,compile_fail
571 /// mod m { macro_rules! foo { () => {} } }
572 /// use m::foo as bar;
575 /// ```rust,compile_fail
576 /// macro_rules! foo { () => {} }
581 /// Well, this code compiles, because the plain path `foo` in `use` is searched
582 /// in the legacy textual scope only.
584 /// macro_rules! foo { () => {} }
587 fn define_macro_rules(
589 module_id: LocalModuleId,
595 self.define_legacy_macro(module_id, name.clone(), macro_);
598 // In Rust, `#[macro_export]` macros are unconditionally visible at the
599 // crate root, even if the parent modules is **not** visible.
603 &[(Some(name), PerNs::macros(macro_, Visibility::Public))],
610 /// Define a legacy textual scoped macro in module
612 /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
613 /// It will clone all macros from parent legacy scope, whose definition is prior to
614 /// the definition of current module.
615 /// And also, `macro_use` on a module will import all legacy macros visible inside to
616 /// current legacy scope, with possible shadowing.
617 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
619 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
622 /// Define a macro 2.0 macro
624 /// The scoped of macro 2.0 macro is equal to normal function
627 module_id: LocalModuleId,
633 self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
634 self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named);
637 /// Define a proc macro
639 /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
640 /// And unconditionally exported.
641 fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) {
644 &[(Some(name), PerNs::macros(macro_, Visibility::Public))],
650 /// Import macros from `#[macro_use] extern crate`.
651 fn import_macros_from_extern_crate(
653 current_module_id: LocalModuleId,
654 extern_crate: &item_tree::ExternCrate,
657 "importing macros from extern crate: {:?} ({:?})",
659 self.def_map.edition,
662 let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
664 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
665 if m == self.def_map.module_id(current_module_id) {
666 cov_mark::hit!(ignore_macro_use_extern_crate_self);
670 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
671 self.import_all_macros_exported(current_module_id, m.krate);
675 /// Import all exported macros from another crate
677 /// Exported macros are just all macros in the root module scope.
678 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
679 /// created by `use` in the root module, ignoring the visibility of `use`.
680 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
681 let def_map = self.db.crate_def_map(krate);
682 for (name, def) in def_map[def_map.root].scope.macros() {
683 // `macro_use` only bring things into legacy scope.
684 self.define_legacy_macro(current_module_id, name.clone(), def);
688 /// Tries to resolve every currently unresolved import.
689 fn resolve_imports(&mut self) -> ReachedFixedPoint {
690 let mut res = ReachedFixedPoint::Yes;
691 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
692 let imports = imports
694 .filter_map(|mut directive| {
695 directive.status = self.resolve_import(directive.module_id, &directive.import);
696 match directive.status {
697 PartialResolvedImport::Indeterminate(_) => {
698 self.record_resolved_import(&directive);
699 // FIXME: For avoid performance regression,
700 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
701 self.resolved_imports.push(directive);
702 res = ReachedFixedPoint::No;
705 PartialResolvedImport::Resolved(_) => {
706 self.record_resolved_import(&directive);
707 self.resolved_imports.push(directive);
708 res = ReachedFixedPoint::No;
711 PartialResolvedImport::Unresolved => Some(directive),
715 self.unresolved_imports = imports;
719 fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
720 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
721 if import.is_extern_crate {
722 let res = self.def_map.resolve_name_in_extern_prelude(
727 .expect("extern crate should have been desugared to one-element path"),
730 PartialResolvedImport::Unresolved
732 PartialResolvedImport::Resolved(res)
735 let res = self.def_map.resolve_path_fp_with_macro(
740 BuiltinShadowMode::Module,
743 let def = res.resolved_def;
744 if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
745 return PartialResolvedImport::Unresolved;
748 if let Some(krate) = res.krate {
749 if krate != self.def_map.krate {
750 return PartialResolvedImport::Resolved(def);
754 // Check whether all namespace is resolved
755 if def.take_types().is_some()
756 && def.take_values().is_some()
757 && def.take_macros().is_some()
759 PartialResolvedImport::Resolved(def)
761 PartialResolvedImport::Indeterminate(def)
766 fn record_resolved_import(&mut self, directive: &ImportDirective) {
767 let module_id = directive.module_id;
768 let import = &directive.import;
769 let def = directive.status.namespaces();
772 .resolve_visibility(self.db, module_id, &directive.import.visibility)
773 .unwrap_or(Visibility::Public);
776 log::debug!("glob import: {:?}", import);
777 match def.take_types() {
778 Some(ModuleDefId::ModuleId(m)) => {
779 if import.is_prelude {
780 // Note: This dodgily overrides the injected prelude. The rustc
781 // implementation seems to work the same though.
782 cov_mark::hit!(std_prelude);
783 self.def_map.prelude = Some(m);
784 } else if m.krate != self.def_map.krate {
785 cov_mark::hit!(glob_across_crates);
786 // glob import from other crate => we can just import everything once
787 let item_map = m.def_map(self.db);
788 let scope = &item_map[m.local_id].scope;
790 // Module scoped macros is included
793 // only keep visible names...
795 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
797 .filter(|(_, res)| !res.is_none())
798 .collect::<Vec<_>>();
800 self.update(module_id, &items, vis, ImportType::Glob);
802 // glob import from same crate => we do an initial
803 // import, and then need to propagate any further
806 let scope = if m.block == self.def_map.block_id() {
807 &self.def_map[m.local_id].scope
809 def_map = m.def_map(self.db);
810 &def_map[m.local_id].scope
813 // Module scoped macros is included
816 // only keep visible names...
820 res.filter_visibility(|v| {
821 v.is_visible_from_def_map(self.db, &self.def_map, module_id)
825 .filter(|(_, res)| !res.is_none())
826 .collect::<Vec<_>>();
828 self.update(module_id, &items, vis, ImportType::Glob);
829 // record the glob import in case we add further items
830 let glob = self.glob_imports.entry(m.local_id).or_default();
831 if !glob.iter().any(|(mid, _)| *mid == module_id) {
832 glob.push((module_id, vis));
836 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
837 cov_mark::hit!(glob_enum);
838 // glob import from enum => just import all the variants
840 // XXX: urgh, so this works by accident! Here, we look at
841 // the enum data, and, in theory, this might require us to
842 // look back at the crate_def_map, creating a cycle. For
843 // example, `enum E { crate::some_macro!(); }`. Luckily, the
844 // only kind of macro that is allowed inside enum is a
845 // `cfg_macro`, and we don't need to run name resolution for
846 // it, but this is sheer luck!
847 let enum_data = self.db.enum_data(e);
848 let resolutions = enum_data
851 .map(|(local_id, variant_data)| {
852 let name = variant_data.name.clone();
853 let variant = EnumVariantId { parent: e, local_id };
854 let res = PerNs::both(variant.into(), variant.into(), vis);
857 .collect::<Vec<_>>();
858 self.update(module_id, &resolutions, vis, ImportType::Glob);
861 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
864 log::debug!("glob import {:?} didn't resolve as type", import);
868 let name = match &import.alias {
869 Some(ImportAlias::Alias(name)) => Some(name.clone()),
870 Some(ImportAlias::Underscore) => None,
871 None => match import.path.segments().last() {
872 Some(last_segment) => Some(last_segment.clone()),
874 cov_mark::hit!(bogus_paths);
880 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
882 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
883 if import.is_extern_crate && module_id == self.def_map.root {
884 if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) {
885 self.def_map.extern_prelude.insert(name.clone(), def);
889 self.update(module_id, &[(name, def)], vis, ImportType::Named);
895 module_id: LocalModuleId,
896 resolutions: &[(Option<Name>, PerNs)],
898 import_type: ImportType,
900 self.db.unwind_if_cancelled();
901 self.update_recursive(module_id, resolutions, vis, import_type, 0)
906 module_id: LocalModuleId,
907 resolutions: &[(Option<Name>, PerNs)],
908 // All resolutions are imported with this visibility; the visibilities in
909 // the `PerNs` values are ignored and overwritten
911 import_type: ImportType,
914 if depth > GLOB_RECURSION_LIMIT {
915 // prevent stack overflows (but this shouldn't be possible)
916 panic!("infinite recursion in glob imports!");
918 let mut changed = false;
920 for (name, res) in resolutions {
923 let scope = &mut self.def_map.modules[module_id].scope;
924 changed |= scope.push_res_with_import(
925 &mut self.from_glob_import,
926 (module_id, name.clone()),
927 res.with_visibility(vis),
932 let tr = match res.take_types() {
933 Some(ModuleDefId::TraitId(tr)) => tr,
935 log::debug!("non-trait `_` import of {:?}", other);
940 let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
941 let should_update = match old_vis {
944 let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| {
945 panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr);
948 if max_vis == old_vis {
951 cov_mark::hit!(upgrade_underscore_visibility);
959 self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
968 let glob_imports = self
972 .flat_map(|v| v.iter())
973 .filter(|(glob_importing_module, _)| {
974 // we know all resolutions have the same visibility (`vis`), so we
975 // just need to check that once
976 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
979 .collect::<Vec<_>>();
981 for (glob_importing_module, glob_import_vis) in glob_imports {
982 self.update_recursive(
983 glob_importing_module,
992 fn resolve_macros(&mut self) -> ReachedFixedPoint {
993 let mut macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
994 let mut resolved = Vec::new();
995 let mut res = ReachedFixedPoint::Yes;
996 macros.retain(|directive| {
997 let resolver = |path| {
998 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1001 directive.module_id,
1003 BuiltinShadowMode::Module,
1005 resolved_res.resolved_def.take_macros()
1008 match &directive.kind {
1009 MacroDirectiveKind::FnLike { ast_id, fragment } => {
1010 match macro_call_as_call_id(
1018 Ok(Ok(call_id)) => {
1019 resolved.push((directive.module_id, call_id, directive.depth));
1020 res = ReachedFixedPoint::No;
1023 Err(UnresolvedMacro { .. }) | Ok(Err(_)) => {}
1026 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
1027 match derive_macro_as_call_id(
1035 resolved.push((directive.module_id, call_id, directive.depth));
1036 res = ReachedFixedPoint::No;
1039 Err(UnresolvedMacro { .. }) => (),
1042 MacroDirectiveKind::Attr { ast_id, mod_item, attr } => {
1043 if let Some(ident) = ast_id.path.as_ident() {
1044 if let Some(helpers) = self.derive_helpers_in_scope.get(&ast_id.ast_id) {
1045 if helpers.contains(ident) {
1046 cov_mark::hit!(resolved_derive_helper);
1048 // Resolved to derive helper. Collect the item's attributes again,
1049 // starting after the derive helper.
1050 let file_id = ast_id.ast_id.file_id;
1051 let item_tree = self.db.file_item_tree(file_id);
1052 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1053 self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
1055 def_collector: &mut *self,
1056 macro_depth: directive.depth,
1057 module_id: directive.module_id,
1059 item_tree: &item_tree,
1062 .collect(&[*mod_item]);
1064 // Remove the original directive since we resolved it.
1065 res = ReachedFixedPoint::No;
1071 if !self.db.enable_proc_attr_macros() {
1075 // Not resolved to a derive helper, so try to resolve as a macro.
1076 match attr_macro_as_call_id(
1084 let loc: MacroCallLoc = self.db.lookup_intern_macro(call_id);
1085 if let MacroDefKind::ProcMacro(exp, ..) = &loc.def.kind {
1087 // Proc macros that cannot be expanded are treated as not
1088 // resolved, in order to fall back later.
1089 self.def_map.diagnostics.push(
1090 DefDiagnostic::unresolved_proc_macro(
1091 directive.module_id,
1096 let file_id = ast_id.ast_id.file_id;
1097 let item_tree = self.db.file_item_tree(file_id);
1098 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1100 .insert(InFile::new(file_id, *mod_item), attr.id);
1102 def_collector: &mut *self,
1103 macro_depth: directive.depth,
1104 module_id: directive.module_id,
1106 item_tree: &item_tree,
1109 .collect(&[*mod_item]);
1111 // Remove the macro directive.
1116 self.def_map.modules[directive.module_id]
1118 .add_attr_macro_invoc(ast_id.ast_id, call_id);
1120 resolved.push((directive.module_id, call_id, directive.depth));
1121 res = ReachedFixedPoint::No;
1124 Err(UnresolvedMacro { .. }) => (),
1131 // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1132 self.unresolved_macros.extend(macros);
1134 for (module_id, macro_call_id, depth) in resolved {
1135 self.collect_macro_expansion(module_id, macro_call_id, depth);
1141 fn collect_macro_expansion(
1143 module_id: LocalModuleId,
1144 macro_call_id: MacroCallId,
1147 if depth > EXPANSION_DEPTH_LIMIT {
1148 cov_mark::hit!(macro_expansion_overflow);
1149 log::warn!("macro expansion is too deep");
1152 let file_id = macro_call_id.as_file();
1154 // First, fetch the raw expansion result for purposes of error reporting. This goes through
1155 // `macro_expand_error` to avoid depending on the full expansion result (to improve
1157 let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
1158 let err = self.db.macro_expand_error(macro_call_id);
1159 if let Some(err) = err {
1160 let diag = match err {
1161 hir_expand::ExpandError::UnresolvedProcMacro => {
1162 // Missing proc macros are non-fatal, so they are handled specially.
1163 DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
1165 _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
1168 self.def_map.diagnostics.push(diag);
1171 // If we've just resolved a derive, record its helper attributes.
1172 if let MacroCallKind::Derive { ast_id, .. } = &loc.kind {
1173 if loc.def.krate != self.def_map.krate {
1174 let def_map = self.db.crate_def_map(loc.def.krate);
1175 if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
1176 if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
1177 self.derive_helpers_in_scope
1180 .extend(helpers.iter().cloned());
1186 // Then, fetch and process the item tree. This will reuse the expansion result from above.
1187 let item_tree = self.db.file_item_tree(file_id);
1188 let mod_dir = self.mod_dirs[&module_id].clone();
1190 def_collector: &mut *self,
1194 item_tree: &item_tree,
1197 .collect(item_tree.top_level_items());
1200 fn finish(mut self) -> DefMap {
1201 // Emit diagnostics for all remaining unexpanded macros.
1203 for directive in &self.unresolved_macros {
1204 match &directive.kind {
1205 MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
1211 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1214 directive.module_id,
1216 BuiltinShadowMode::Module,
1218 resolved_res.resolved_def.take_macros()
1223 Err(UnresolvedMacro { path }) => {
1224 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1225 directive.module_id,
1231 MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
1232 // FIXME: we might want to diagnose this too
1237 // Emit diagnostics for all remaining unresolved imports.
1239 // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
1240 // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
1241 // crate names. Then we emit diagnostics for unresolved imports, but only if the import
1242 // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
1243 // heuristic, but it works in practice.
1244 let mut diagnosed_extern_crates = FxHashSet::default();
1245 for directive in &self.unresolved_imports {
1246 if let ImportSource::ExternCrate(krate) = directive.import.source {
1247 let item_tree = krate.item_tree(self.db);
1248 let extern_crate = &item_tree[krate.value];
1250 diagnosed_extern_crates.insert(extern_crate.name.clone());
1252 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
1253 directive.module_id,
1254 InFile::new(krate.file_id(), extern_crate.ast_id),
1259 for directive in &self.unresolved_imports {
1260 if let ImportSource::Import { id: import, use_tree } = &directive.import.source {
1261 match (directive.import.path.segments().first(), &directive.import.path.kind) {
1262 (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
1263 if diagnosed_extern_crates.contains(krate) {
1270 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1271 directive.module_id,
1282 /// Walks a single module, populating defs, imports and macros
1283 struct ModCollector<'a, 'b> {
1284 def_collector: &'a mut DefCollector<'b>,
1286 module_id: LocalModuleId,
1288 item_tree: &'a ItemTree,
1292 impl ModCollector<'_, '_> {
1293 fn collect(&mut self, items: &[ModItem]) {
1294 let krate = self.def_collector.def_map.krate;
1296 // Note: don't assert that inserted value is fresh: it's simply not true
1298 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1300 // Prelude module is always considered to be `#[macro_use]`.
1301 if let Some(prelude_module) = self.def_collector.def_map.prelude {
1302 if prelude_module.krate != krate {
1303 cov_mark::hit!(prelude_is_macro_use);
1304 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1308 // This should be processed eagerly instead of deferred to resolving.
1309 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1312 let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
1313 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
1314 if let ModItem::ExternCrate(id) = item {
1315 let import = self.item_tree[*id].clone();
1316 let attrs = self.item_tree.attrs(
1317 self.def_collector.db,
1319 ModItem::from(*id).into(),
1321 if attrs.by_key("macro_use").exists() {
1322 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
1328 for &item in items {
1329 let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1330 if let Some(cfg) = attrs.cfg() {
1331 if !self.is_cfg_enabled(&cfg) {
1332 self.emit_unconfigured_diagnostic(item, &cfg);
1337 if let Err(()) = self.resolve_attributes(&attrs, item) {
1338 // Do not process the item. It has at least one non-builtin attribute, so the
1339 // fixed-point algorithm is required to resolve the rest of them.
1343 let module = self.def_collector.def_map.module_id(self.module_id);
1347 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
1348 ModItem::Import(import_id) => {
1349 let module_id = self.module_id;
1350 let imports = Import::from_use(
1351 self.def_collector.db,
1354 ItemTreeId::new(self.file_id, import_id),
1356 self.def_collector.unresolved_imports.extend(imports.into_iter().map(
1357 |import| ImportDirective {
1360 status: PartialResolvedImport::Unresolved,
1364 ModItem::ExternCrate(import_id) => {
1365 self.def_collector.unresolved_imports.push(ImportDirective {
1366 module_id: self.module_id,
1367 import: Import::from_extern_crate(
1368 self.def_collector.db,
1371 ItemTreeId::new(self.file_id, import_id),
1373 status: PartialResolvedImport::Unresolved,
1376 ModItem::ExternBlock(block) => self.collect(&self.item_tree[block].children),
1377 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
1378 ModItem::MacroRules(id) => self.collect_macro_rules(id),
1379 ModItem::MacroDef(id) => self.collect_macro_def(id),
1380 ModItem::Impl(imp) => {
1381 let module = self.def_collector.def_map.module_id(self.module_id);
1383 ImplLoc { container: module, id: ItemTreeId::new(self.file_id, imp) }
1384 .intern(self.def_collector.db);
1385 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1387 ModItem::Function(id) => {
1388 let func = &self.item_tree[id];
1390 let ast_id = InFile::new(self.file_id, func.ast_id);
1391 self.collect_proc_macro_def(&func.name, ast_id, &attrs);
1393 def = Some(DefData {
1395 container: module.into(),
1396 id: ItemTreeId::new(self.file_id, id),
1398 .intern(self.def_collector.db)
1401 visibility: &self.item_tree[func.visibility],
1402 has_constructor: false,
1405 ModItem::Struct(id) => {
1406 let it = &self.item_tree[id];
1408 def = Some(DefData {
1409 id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1410 .intern(self.def_collector.db)
1413 visibility: &self.item_tree[it.visibility],
1414 has_constructor: !matches!(it.fields, Fields::Record(_)),
1417 ModItem::Union(id) => {
1418 let it = &self.item_tree[id];
1420 def = Some(DefData {
1421 id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1422 .intern(self.def_collector.db)
1425 visibility: &self.item_tree[it.visibility],
1426 has_constructor: false,
1429 ModItem::Enum(id) => {
1430 let it = &self.item_tree[id];
1432 def = Some(DefData {
1433 id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1434 .intern(self.def_collector.db)
1437 visibility: &self.item_tree[it.visibility],
1438 has_constructor: false,
1441 ModItem::Const(id) => {
1442 let it = &self.item_tree[id];
1443 let const_id = ConstLoc {
1444 container: module.into(),
1445 id: ItemTreeId::new(self.file_id, id),
1447 .intern(self.def_collector.db);
1451 def = Some(DefData {
1452 id: const_id.into(),
1454 visibility: &self.item_tree[it.visibility],
1455 has_constructor: false,
1459 // const _: T = ...;
1460 self.def_collector.def_map.modules[self.module_id]
1462 .define_unnamed_const(const_id);
1466 ModItem::Static(id) => {
1467 let it = &self.item_tree[id];
1469 def = Some(DefData {
1470 id: StaticLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1471 .intern(self.def_collector.db)
1474 visibility: &self.item_tree[it.visibility],
1475 has_constructor: false,
1478 ModItem::Trait(id) => {
1479 let it = &self.item_tree[id];
1481 def = Some(DefData {
1482 id: TraitLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1483 .intern(self.def_collector.db)
1486 visibility: &self.item_tree[it.visibility],
1487 has_constructor: false,
1490 ModItem::TypeAlias(id) => {
1491 let it = &self.item_tree[id];
1493 def = Some(DefData {
1495 container: module.into(),
1496 id: ItemTreeId::new(self.file_id, id),
1498 .intern(self.def_collector.db)
1501 visibility: &self.item_tree[it.visibility],
1502 has_constructor: false,
1507 if let Some(DefData { id, name, visibility, has_constructor }) = def {
1508 self.def_collector.def_map.modules[self.module_id].scope.define_def(id);
1512 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1513 .unwrap_or(Visibility::Public);
1514 self.def_collector.update(
1516 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1524 fn collect_module(&mut self, module: &Mod, attrs: &Attrs) {
1525 let path_attr = attrs.by_key("path").string_value();
1526 let is_macro_use = attrs.by_key("macro_use").exists();
1527 match &module.kind {
1528 // inline module, just recurse
1529 ModKind::Inline { items } => {
1530 let module_id = self.push_child_module(
1531 module.name.clone(),
1532 AstId::new(self.file_id, module.ast_id),
1534 &self.item_tree[module.visibility],
1537 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1540 def_collector: &mut *self.def_collector,
1541 macro_depth: self.macro_depth,
1543 file_id: self.file_id,
1544 item_tree: self.item_tree,
1549 self.import_all_legacy_macros(module_id);
1553 // out of line module, resolve, parse and recurse
1554 ModKind::Outline {} => {
1555 let ast_id = AstId::new(self.file_id, module.ast_id);
1556 let db = self.def_collector.db;
1557 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) {
1558 Ok((file_id, is_mod_rs, mod_dir)) => {
1559 let item_tree = db.file_item_tree(file_id.into());
1561 .top_level_attrs(db, self.def_collector.def_map.krate)
1563 .map_or(true, |cfg| {
1564 self.def_collector.cfg_options.check(&cfg) != Some(false)
1567 let module_id = self.push_child_module(
1568 module.name.clone(),
1570 Some((file_id, is_mod_rs)),
1571 &self.item_tree[module.visibility],
1574 def_collector: &mut *self.def_collector,
1575 macro_depth: self.macro_depth,
1577 file_id: file_id.into(),
1578 item_tree: &item_tree,
1581 .collect(item_tree.top_level_items());
1584 .top_level_attrs(db, self.def_collector.def_map.krate)
1585 .by_key("macro_use")
1588 self.import_all_legacy_macros(module_id);
1593 self.def_collector.def_map.diagnostics.push(
1594 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidate),
1602 fn push_child_module(
1605 declaration: AstId<ast::Module>,
1606 definition: Option<(FileId, bool)>,
1607 visibility: &crate::visibility::RawVisibility,
1608 ) -> LocalModuleId {
1612 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1613 .unwrap_or(Visibility::Public);
1614 let modules = &mut self.def_collector.def_map.modules;
1615 let res = modules.alloc(ModuleData::default());
1616 modules[res].parent = Some(self.module_id);
1617 modules[res].origin = match definition {
1618 None => ModuleOrigin::Inline { definition: declaration },
1619 Some((definition, is_mod_rs)) => {
1620 ModuleOrigin::File { declaration, definition, is_mod_rs }
1623 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
1624 modules[res].scope.define_legacy_macro(name, mac)
1626 modules[self.module_id].children.insert(name.clone(), res);
1627 let module = self.def_collector.def_map.module_id(res);
1628 let def: ModuleDefId = module.into();
1629 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1630 self.def_collector.update(
1632 &[(Some(name), PerNs::from_def(def, vis, false))],
1639 /// Resolves attributes on an item.
1641 /// Returns `Err` when some attributes could not be resolved to builtins and have been
1642 /// registered as unresolved.
1644 /// If `ignore_up_to` is `Some`, attributes precending and including that attribute will be
1645 /// assumed to be resolved already.
1646 fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> {
1647 let mut ignore_up_to =
1648 self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied();
1652 // FIXME: this should not be required, all attributes on an item should have a
1654 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1655 // #[cfg_attr(not(off), unresolved, unresolved)]
1657 // We should come up with a different way to ID attributes.
1660 .skip_while(|attr| match ignore_up_to {
1661 Some(id) if attr.id == id => {
1662 ignore_up_to = None;
1670 if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
1671 self.collect_derive(attr, mod_item);
1672 } else if self.is_builtin_or_registered_attr(&attr.path) {
1675 log::debug!("non-builtin attribute {}", attr.path);
1677 let ast_id = AstIdWithPath::new(
1679 mod_item.ast_id(self.item_tree),
1680 attr.path.as_ref().clone(),
1682 self.def_collector.unresolved_macros.push(MacroDirective {
1683 module_id: self.module_id,
1684 depth: self.macro_depth + 1,
1685 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
1695 fn is_builtin_or_registered_attr(&self, path: &ModPath) -> bool {
1696 if path.kind == PathKind::Plain {
1697 if let Some(tool_module) = path.segments().first() {
1698 let tool_module = tool_module.to_string();
1699 if builtin_attr::TOOL_MODULES
1702 .chain(self.def_collector.registered_tools.iter().map(|s| &**s))
1703 .any(|m| tool_module == *m)
1709 if let Some(name) = path.as_ident() {
1710 let name = name.to_string();
1711 if builtin_attr::INERT_ATTRIBUTES
1713 .chain(builtin_attr::EXTRA_ATTRIBUTES)
1715 .chain(self.def_collector.registered_attrs.iter().map(|s| &**s))
1716 .any(|attr| name == *attr)
1726 fn collect_derive(&mut self, attr: &Attr, mod_item: ModItem) {
1727 let ast_id: FileAstId<ast::Item> = match mod_item {
1728 ModItem::Struct(it) => self.item_tree[it].ast_id.upcast(),
1729 ModItem::Union(it) => self.item_tree[it].ast_id.upcast(),
1730 ModItem::Enum(it) => self.item_tree[it].ast_id.upcast(),
1732 // Cannot use derive on this item.
1738 match attr.parse_derive() {
1739 Some(derive_macros) => {
1740 for path in derive_macros {
1741 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1742 self.def_collector.unresolved_macros.push(MacroDirective {
1743 module_id: self.module_id,
1744 depth: self.macro_depth + 1,
1745 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: attr.id },
1751 log::debug!("malformed derive: {:?}", attr);
1756 /// If `attrs` registers a procedural macro, collects its definition.
1757 fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
1758 // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
1759 if let Some(proc_macro) = attrs.parse_proc_macro_decl(func_name) {
1760 self.def_collector.export_proc_macro(proc_macro, ast_id);
1764 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
1765 let krate = self.def_collector.def_map.krate;
1766 let mac = &self.item_tree[id];
1767 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1768 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1770 let export_attr = attrs.by_key("macro_export");
1772 let is_export = export_attr.exists();
1773 let is_local_inner = if is_export {
1774 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
1775 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
1776 ident.text.contains("local_inner_macros")
1784 // Case 1: builtin macros
1785 if attrs.by_key("rustc_builtin_macro").exists() {
1786 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1788 let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1790 // FIXME: a hacky way to create a Name from string.
1791 name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1796 let krate = self.def_collector.def_map.krate;
1797 match find_builtin_macro(name, krate, ast_id) {
1799 self.def_collector.define_macro_rules(
1811 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1816 // Case 2: normal `macro_rules!` macro
1817 let macro_id = MacroDefId {
1818 krate: self.def_collector.def_map.krate,
1819 kind: MacroDefKind::Declarative(ast_id),
1820 local_inner: is_local_inner,
1822 self.def_collector.define_macro_rules(
1830 fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>) {
1831 let krate = self.def_collector.def_map.krate;
1832 let mac = &self.item_tree[id];
1833 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1835 // Case 1: bulitin macros
1836 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1837 if attrs.by_key("rustc_builtin_macro").exists() {
1838 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1839 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
1843 self.def_collector.define_macro_def(
1847 &self.item_tree[mac.visibility],
1855 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1860 // Case 2: normal `macro`
1861 let macro_id = MacroDefId {
1862 krate: self.def_collector.def_map.krate,
1863 kind: MacroDefKind::Declarative(ast_id),
1867 self.def_collector.define_macro_def(
1871 &self.item_tree[mac.visibility],
1875 fn collect_macro_call(&mut self, mac: &MacroCall) {
1876 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone());
1878 // Case 1: try to resolve in legacy scope and expand macro_rules
1879 let mut error = None;
1880 match macro_call_as_call_id(
1883 self.def_collector.db,
1884 self.def_collector.def_map.krate,
1886 path.as_ident().and_then(|name| {
1887 self.def_collector.def_map.with_ancestor_maps(
1888 self.def_collector.db,
1890 &mut |map, module| map[module].scope.get_legacy_macro(&name),
1895 error.get_or_insert(err);
1898 Ok(Ok(macro_call_id)) => {
1899 // Legacy macros need to be expanded immediately, so that any macros they produce
1901 self.def_collector.collect_macro_expansion(
1904 self.macro_depth + 1,
1910 // Built-in macro failed eager expansion.
1912 // FIXME: don't parse the file here
1913 let fragment = hir_expand::to_fragment_kind(
1914 &ast_id.ast_id.to_node(self.def_collector.db.upcast()),
1916 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1918 MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
1919 error.unwrap().to_string(),
1923 Err(UnresolvedMacro { .. }) => (),
1926 // Case 2: resolve in module scope, expand during name resolution.
1927 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
1928 if ast_id.path.is_ident() {
1929 ast_id.path.kind = PathKind::Super(0);
1932 self.def_collector.unresolved_macros.push(MacroDirective {
1933 module_id: self.module_id,
1934 depth: self.macro_depth + 1,
1935 kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
1939 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
1940 let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
1941 for (name, macro_) in macros {
1942 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
1946 fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
1947 self.def_collector.cfg_options.check(cfg) != Some(false)
1950 fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
1951 let ast_id = item.ast_id(self.item_tree);
1953 let ast_id = InFile::new(self.file_id, ast_id);
1954 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
1958 self.def_collector.cfg_options.clone(),
1965 use crate::{db::DefDatabase, test_db::TestDB};
1966 use base_db::{fixture::WithFixture, SourceDatabase};
1970 fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
1971 let mut collector = DefCollector {
1974 glob_imports: FxHashMap::default(),
1975 unresolved_imports: Vec::new(),
1976 resolved_imports: Vec::new(),
1977 unresolved_macros: Vec::new(),
1978 mod_dirs: FxHashMap::default(),
1979 cfg_options: &CfgOptions::default(),
1980 proc_macros: Default::default(),
1981 exports_proc_macros: false,
1982 from_glob_import: Default::default(),
1983 skip_attrs: Default::default(),
1984 derive_helpers_in_scope: Default::default(),
1985 registered_attrs: Default::default(),
1986 registered_tools: Default::default(),
1988 collector.seed_with_top_level();
1989 collector.collect();
1993 fn do_resolve(code: &str) -> DefMap {
1994 let (db, _file_id) = TestDB::with_single_file(&code);
1995 let krate = db.test_crate();
1997 let edition = db.crate_graph()[krate].edition;
1998 let def_map = DefMap::empty(krate, edition);
1999 do_collect_defs(&db, def_map)
2003 fn test_macro_expand_will_stop_1() {
2007 ($($ty:ty)*) => { foo!($($ty)*); }
2014 #[ignore] // this test does succeed, but takes quite a while :/
2016 fn test_macro_expand_will_stop_2() {
2020 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }