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.
7 builtin_derive::find_builtin_derive,
8 builtin_macro::find_builtin_macro,
9 name::{name, AsName, Name},
10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
12 use ra_cfg::CfgOptions;
13 use ra_db::{CrateId, FileId};
15 use rustc_hash::FxHashMap;
16 use test_utils::tested_by;
22 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
23 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
25 path::{ModPath, PathKind},
27 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
28 LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc,
29 TypeAliasLoc, UnionLoc,
32 pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
33 let crate_graph = db.crate_graph();
35 // populate external prelude
36 for dep in crate_graph.dependencies(def_map.krate) {
37 let dep_def_map = db.crate_def_map(dep.crate_id);
38 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
39 def_map.extern_prelude.insert(
41 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
44 // look for the prelude
45 // If the dependency defines a prelude, we overwrite an already defined
46 // prelude. This is necessary to import the "std" prelude if a crate
47 // depends on both "core" and "std".
48 let dep_def_map = db.crate_def_map(dep.crate_id);
49 if dep_def_map.prelude.is_some() {
50 def_map.prelude = dep_def_map.prelude;
54 let cfg_options = crate_graph.cfg_options(def_map.krate);
56 let mut collector = DefCollector {
59 glob_imports: FxHashMap::default(),
60 unresolved_imports: Vec::new(),
61 resolved_imports: Vec::new(),
63 unexpanded_macros: Vec::new(),
64 unexpanded_attribute_macros: Vec::new(),
65 mod_dirs: FxHashMap::default(),
72 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
73 enum PartialResolvedImport {
74 /// None of any namespaces is resolved
76 /// One of namespaces is resolved
78 /// All namespaces are resolved, OR it is came from other crate
82 impl PartialResolvedImport {
83 fn namespaces(&self) -> PerNs {
85 PartialResolvedImport::Unresolved => PerNs::none(),
86 PartialResolvedImport::Indeterminate(ns) => *ns,
87 PartialResolvedImport::Resolved(ns) => *ns,
92 #[derive(Clone, Debug, Eq, PartialEq)]
93 struct ImportDirective {
94 module_id: LocalModuleId,
95 import_id: LocalImportId,
96 import: raw::ImportData,
97 status: PartialResolvedImport,
100 #[derive(Clone, Debug, Eq, PartialEq)]
101 struct MacroDirective {
102 module_id: LocalModuleId,
103 ast_id: AstId<ast::MacroCall>,
105 legacy: Option<MacroCallId>,
108 /// Walks the tree of module recursively
109 struct DefCollector<'a, DB> {
111 def_map: CrateDefMap,
112 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
113 unresolved_imports: Vec<ImportDirective>,
114 resolved_imports: Vec<ImportDirective>,
115 unexpanded_macros: Vec<MacroDirective>,
116 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
117 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
118 cfg_options: &'a CfgOptions,
121 impl<DB> DefCollector<'_, DB>
125 fn collect(&mut self) {
126 let crate_graph = self.db.crate_graph();
127 let file_id = crate_graph.crate_root(self.def_map.krate);
128 let raw_items = self.db.raw_items(file_id.into());
129 let module_id = self.def_map.root;
130 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
132 def_collector: &mut *self,
134 file_id: file_id.into(),
135 raw_items: &raw_items,
136 mod_dir: ModDir::root(),
138 .collect(raw_items.items());
140 // main name resolution fixed-point loop.
143 self.db.check_canceled();
144 self.resolve_imports();
146 match self.resolve_macros() {
147 ReachedFixedPoint::Yes => break,
148 ReachedFixedPoint::No => i += 1,
151 log::error!("name resolution is stuck");
156 // Resolve all indeterminate resolved imports again
157 // As some of the macros will expand newly import shadowing partial resolved imports
158 // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports`
160 let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
161 if let PartialResolvedImport::Indeterminate(_) = directive.status {
162 let mut directive = directive.clone();
163 directive.status = PartialResolvedImport::Unresolved;
169 self.unresolved_imports.extend(partial_resolved);
170 self.resolve_imports();
172 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
173 // show unresolved imports in completion, etc
174 for directive in unresolved_imports {
175 self.record_resolved_import(&directive)
179 /// Define a macro with `macro_rules`.
181 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
182 /// then it is also defined in the root module scope.
183 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
185 /// It is surprising that the macro will never be in the current module scope.
186 /// These code fails with "unresolved import/macro",
187 /// ```rust,compile_fail
188 /// mod m { macro_rules! foo { () => {} } }
189 /// use m::foo as bar;
192 /// ```rust,compile_fail
193 /// macro_rules! foo { () => {} }
198 /// Well, this code compiles, because the plain path `foo` in `use` is searched
199 /// in the legacy textual scope only.
201 /// macro_rules! foo { () => {} }
206 module_id: LocalModuleId,
212 self.define_legacy_macro(module_id, name.clone(), macro_);
215 // In Rust, `#[macro_export]` macros are unconditionally visible at the
216 // crate root, even if the parent modules is **not** visible.
221 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
226 /// Define a legacy textual scoped macro in module
228 /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module.
229 /// It will clone all macros from parent legacy scope, whose definition is prior to
230 /// the definition of current module.
231 /// And also, `macro_use` on a module will import all legacy macros visable inside to
232 /// current legacy scope, with possible shadowing.
233 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
235 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
238 /// Import macros from `#[macro_use] extern crate`.
239 fn import_macros_from_extern_crate(
241 current_module_id: LocalModuleId,
242 import: &raw::ImportData,
245 "importing macros from extern crate: {:?} ({:?})",
247 self.def_map.edition,
250 let res = self.def_map.resolve_name_in_extern_prelude(
254 .expect("extern crate should have been desugared to one-element path"),
257 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
258 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
259 self.import_all_macros_exported(current_module_id, m.krate);
263 /// Import all exported macros from another crate
265 /// Exported macros are just all macros in the root module scope.
266 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
267 /// created by `use` in the root module, ignoring the visibility of `use`.
268 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
269 let def_map = self.db.crate_def_map(krate);
270 for (name, def) in def_map[def_map.root].scope.macros() {
271 // `macro_use` only bring things into legacy scope.
272 self.define_legacy_macro(current_module_id, name.clone(), def);
276 /// Import resolution
278 /// This is a fix point algorithm. We resolve imports until no forward
279 /// progress in resolving imports is made
280 fn resolve_imports(&mut self) {
281 let mut n_previous_unresolved = self.unresolved_imports.len() + 1;
283 while self.unresolved_imports.len() < n_previous_unresolved {
284 n_previous_unresolved = self.unresolved_imports.len();
285 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
286 for mut directive in imports {
287 directive.status = self.resolve_import(directive.module_id, &directive.import);
289 match directive.status {
290 PartialResolvedImport::Indeterminate(_) => {
291 self.record_resolved_import(&directive);
292 // FIXME: For avoid performance regression,
293 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
294 self.resolved_imports.push(directive)
296 PartialResolvedImport::Resolved(_) => {
297 self.record_resolved_import(&directive);
298 self.resolved_imports.push(directive)
300 PartialResolvedImport::Unresolved => {
301 self.unresolved_imports.push(directive);
310 module_id: LocalModuleId,
311 import: &raw::ImportData,
312 ) -> PartialResolvedImport {
313 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
314 if import.is_extern_crate {
315 let res = self.def_map.resolve_name_in_extern_prelude(
319 .expect("extern crate should have been desugared to one-element path"),
321 PartialResolvedImport::Resolved(res)
323 let res = self.def_map.resolve_path_fp_with_macro(
328 BuiltinShadowMode::Module,
331 let def = res.resolved_def;
332 if res.reached_fixedpoint == ReachedFixedPoint::No {
333 return PartialResolvedImport::Unresolved;
336 if let Some(krate) = res.krate {
337 if krate != self.def_map.krate {
338 return PartialResolvedImport::Resolved(def);
342 // Check whether all namespace is resolved
343 if def.take_types().is_some()
344 && def.take_values().is_some()
345 && def.take_macros().is_some()
347 PartialResolvedImport::Resolved(def)
349 PartialResolvedImport::Indeterminate(def)
354 fn record_resolved_import(&mut self, directive: &ImportDirective) {
355 let module_id = directive.module_id;
356 let import_id = directive.import_id;
357 let import = &directive.import;
358 let def = directive.status.namespaces();
361 log::debug!("glob import: {:?}", import);
362 match def.take_types() {
363 Some(ModuleDefId::ModuleId(m)) => {
364 if import.is_prelude {
365 tested_by!(std_prelude);
366 self.def_map.prelude = Some(m);
367 } else if m.krate != self.def_map.krate {
368 tested_by!(glob_across_crates);
369 // glob import from other crate => we can just import everything once
370 let item_map = self.db.crate_def_map(m.krate);
371 let scope = &item_map[m.local_id].scope;
373 // Module scoped macros is included
377 .map(|(name, res)| (name.clone(), res.clone()))
378 .collect::<Vec<_>>();
380 self.update(module_id, Some(import_id), &items);
382 // glob import from same crate => we do an initial
383 // import, and then need to propagate any further
385 let scope = &self.def_map[m.local_id].scope;
387 // Module scoped macros is included
391 .map(|(name, res)| (name.clone(), res.clone()))
392 .collect::<Vec<_>>();
394 self.update(module_id, Some(import_id), &items);
395 // record the glob import in case we add further items
396 let glob = self.glob_imports.entry(m.local_id).or_default();
397 if !glob.iter().any(|it| *it == (module_id, import_id)) {
398 glob.push((module_id, import_id));
402 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
403 tested_by!(glob_enum);
404 // glob import from enum => just import all the variants
405 let enum_data = self.db.enum_data(e);
406 let resolutions = enum_data
409 .filter_map(|(local_id, variant_data)| {
410 let name = variant_data.name.clone();
411 let variant = EnumVariantId { parent: e, local_id };
412 let res = Resolution {
413 def: PerNs::both(variant.into(), variant.into()),
414 import: Some(import_id),
418 .collect::<Vec<_>>();
419 self.update(module_id, Some(import_id), &resolutions);
422 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
425 log::debug!("glob import {:?} didn't resolve as type", import);
429 match import.path.segments.last() {
430 Some(last_segment) => {
431 let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
432 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
434 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
435 if import.is_extern_crate && module_id == self.def_map.root {
436 if let Some(def) = def.take_types() {
437 self.def_map.extern_prelude.insert(name.clone(), def);
441 let resolution = Resolution { def, import: Some(import_id) };
442 self.update(module_id, Some(import_id), &[(name, resolution)]);
444 None => tested_by!(bogus_paths),
451 module_id: LocalModuleId,
452 import: Option<LocalImportId>,
453 resolutions: &[(Name, Resolution)],
455 self.update_recursive(module_id, import, resolutions, 0)
460 module_id: LocalModuleId,
461 import: Option<LocalImportId>,
462 resolutions: &[(Name, Resolution)],
466 // prevent stack overflows (but this shouldn't be possible)
467 panic!("infinite recursion in glob imports!");
469 let module_items = &mut self.def_map.modules[module_id].scope;
470 let mut changed = false;
471 for (name, res) in resolutions {
472 let existing = module_items.items.entry(name.clone()).or_default();
474 if existing.def.types.is_none() && res.def.types.is_some() {
475 existing.def.types = res.def.types;
476 existing.import = import.or(res.import);
479 if existing.def.values.is_none() && res.def.values.is_some() {
480 existing.def.values = res.def.values;
481 existing.import = import.or(res.import);
484 if existing.def.macros.is_none() && res.def.macros.is_some() {
485 existing.def.macros = res.def.macros;
486 existing.import = import.or(res.import);
490 if existing.def.is_none()
492 && existing.import.is_none()
493 && res.import.is_some()
495 existing.import = res.import;
502 let glob_imports = self
506 .flat_map(|v| v.iter())
508 .collect::<Vec<_>>();
509 for (glob_importing_module, glob_import) in glob_imports {
510 // We pass the glob import so that the tracked import in those modules is that glob import
511 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
515 fn resolve_macros(&mut self) -> ReachedFixedPoint {
516 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
517 let mut attribute_macros =
518 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
519 let mut resolved = Vec::new();
520 let mut res = ReachedFixedPoint::Yes;
521 macros.retain(|directive| {
522 if let Some(call_id) = directive.legacy {
523 res = ReachedFixedPoint::No;
524 resolved.push((directive.module_id, call_id));
528 let resolved_res = self.def_map.resolve_path_fp_with_macro(
533 BuiltinShadowMode::Module,
536 if let Some(def) = resolved_res.resolved_def.take_macros() {
537 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
538 resolved.push((directive.module_id, call_id));
539 res = ReachedFixedPoint::No;
545 attribute_macros.retain(|(module_id, ast_id, path)| {
546 let resolved_res = self.resolve_attribute_macro(path);
548 if let Some(def) = resolved_res {
549 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
550 resolved.push((*module_id, call_id));
551 res = ReachedFixedPoint::No;
558 self.unexpanded_macros = macros;
559 self.unexpanded_attribute_macros = attribute_macros;
561 for (module_id, macro_call_id) in resolved {
562 self.collect_macro_expansion(module_id, macro_call_id);
568 fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
569 // FIXME this is currently super hacky, just enough to support the
571 if let Some(name) = path.as_ident() {
572 // FIXME this should actually be handled with the normal name
573 // resolution; the std lib defines built-in stubs for the derives,
574 // but these are new-style `macro`s, which we don't support yet
575 if let Some(def_id) = find_builtin_derive(name) {
582 fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
583 let file_id: HirFileId = macro_call_id.as_file();
584 let raw_items = self.db.raw_items(file_id);
585 let mod_dir = self.mod_dirs[&module_id].clone();
587 def_collector: &mut *self,
590 raw_items: &raw_items,
593 .collect(raw_items.items());
596 fn finish(self) -> CrateDefMap {
601 /// Walks a single module, populating defs, imports and macros
602 struct ModCollector<'a, D> {
604 module_id: LocalModuleId,
606 raw_items: &'a raw::RawItems,
610 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
614 fn collect(&mut self, items: &[raw::RawItem]) {
615 // Note: don't assert that inserted value is fresh: it's simply not true
617 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
619 // Prelude module is always considered to be `#[macro_use]`.
620 if let Some(prelude_module) = self.def_collector.def_map.prelude {
621 if prelude_module.krate != self.def_collector.def_map.krate {
622 tested_by!(prelude_is_macro_use);
623 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
627 // This should be processed eagerly instead of deferred to resolving.
628 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
631 if self.is_cfg_enabled(&item.attrs) {
632 if let raw::RawItemKind::Import(import_id) = item.kind {
633 let import = self.raw_items[import_id].clone();
634 if import.is_extern_crate && import.is_macro_use {
635 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
642 if self.is_cfg_enabled(&item.attrs) {
644 raw::RawItemKind::Module(m) => {
645 self.collect_module(&self.raw_items[m], &item.attrs)
647 raw::RawItemKind::Import(import_id) => {
648 self.def_collector.unresolved_imports.push(ImportDirective {
649 module_id: self.module_id,
651 import: self.raw_items[import_id].clone(),
652 status: PartialResolvedImport::Unresolved,
655 raw::RawItemKind::Def(def) => {
656 self.define_def(&self.raw_items[def], &item.attrs)
658 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
659 raw::RawItemKind::Impl(imp) => {
660 let module = ModuleId {
661 krate: self.def_collector.def_map.krate,
662 local_id: self.module_id,
664 let ast_id = self.raw_items[imp].ast_id;
666 ImplLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
667 .intern(self.def_collector.db);
668 self.def_collector.def_map.modules[self.module_id].impls.push(impl_id)
675 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
676 let path_attr = attrs.by_key("path").string_value();
677 let is_macro_use = attrs.by_key("macro_use").exists();
679 // inline module, just recurse
680 raw::ModuleData::Definition { name, items, ast_id } => {
682 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
685 def_collector: &mut *self.def_collector,
687 file_id: self.file_id,
688 raw_items: self.raw_items,
689 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
693 self.import_all_legacy_macros(module_id);
696 // out of line module, resolve, parse and recurse
697 raw::ModuleData::Declaration { name, ast_id } => {
698 let ast_id = AstId::new(self.file_id, *ast_id);
699 match self.mod_dir.resolve_declaration(
700 self.def_collector.db,
705 Ok((file_id, mod_dir)) => {
706 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
707 let raw_items = self.def_collector.db.raw_items(file_id.into());
709 def_collector: &mut *self.def_collector,
711 file_id: file_id.into(),
712 raw_items: &raw_items,
715 .collect(raw_items.items());
717 self.import_all_legacy_macros(module_id);
720 Err(candidate) => self.def_collector.def_map.diagnostics.push(
721 DefDiagnostic::UnresolvedModule {
722 module: self.module_id,
732 fn push_child_module(
735 declaration: AstId<ast::Module>,
736 definition: Option<FileId>,
738 let modules = &mut self.def_collector.def_map.modules;
739 let res = modules.alloc(ModuleData::default());
740 modules[res].parent = Some(self.module_id);
741 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
742 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
743 modules[self.module_id].children.insert(name.clone(), res);
744 let resolution = Resolution {
746 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
750 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
754 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
755 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
756 // FIXME: check attrs to see if this is an attribute macro invocation;
757 // in which case we don't add the invocation, just a single attribute
760 self.collect_derives(attrs, def);
762 let name = def.name.clone();
763 let container = ContainerId::ModuleId(module);
764 let def: PerNs = match def.kind {
765 raw::DefKind::Function(ast_id) => {
766 let def = FunctionLoc {
767 container: container.into(),
768 ast_id: AstId::new(self.file_id, ast_id),
770 .intern(self.def_collector.db);
772 PerNs::values(def.into())
774 raw::DefKind::Struct(ast_id) => {
775 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
776 .intern(self.def_collector.db);
777 PerNs::both(def.into(), def.into())
779 raw::DefKind::Union(ast_id) => {
780 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
781 .intern(self.def_collector.db);
782 PerNs::both(def.into(), def.into())
784 raw::DefKind::Enum(ast_id) => {
785 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
786 .intern(self.def_collector.db);
787 PerNs::types(def.into())
789 raw::DefKind::Const(ast_id) => {
791 container: container.into(),
792 ast_id: AstId::new(self.file_id, ast_id),
794 .intern(self.def_collector.db);
796 PerNs::values(def.into())
798 raw::DefKind::Static(ast_id) => {
799 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
800 .intern(self.def_collector.db);
802 PerNs::values(def.into())
804 raw::DefKind::Trait(ast_id) => {
805 let def = TraitLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
806 .intern(self.def_collector.db);
808 PerNs::types(def.into())
810 raw::DefKind::TypeAlias(ast_id) => {
811 let def = TypeAliasLoc {
812 container: container.into(),
813 ast_id: AstId::new(self.file_id, ast_id),
815 .intern(self.def_collector.db);
817 PerNs::types(def.into())
820 let resolution = Resolution { def, import: None };
821 self.def_collector.update(self.module_id, None, &[(name, resolution)])
824 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
825 for derive_subtree in attrs.by_key("derive").tt_values() {
826 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
827 for tt in &derive_subtree.token_trees {
828 let ident = match &tt {
829 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
830 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
831 _ => continue, // anything else would be an error (which we currently ignore)
833 let path = ModPath::from_tt_ident(ident);
835 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
836 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
841 fn collect_macro(&mut self, mac: &raw::MacroData) {
842 let ast_id = AstId::new(self.file_id, mac.ast_id);
844 // Case 0: builtin macros
846 if let Some(name) = &mac.name {
847 let krate = self.def_collector.def_map.krate;
848 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
849 self.def_collector.define_macro(
860 // Case 1: macro rules, define a macro in crate-global mutable scope
861 if is_macro_rules(&mac.path) {
862 if let Some(name) = &mac.name {
863 let macro_id = MacroDefId {
864 ast_id: Some(ast_id),
865 krate: Some(self.def_collector.def_map.krate),
866 kind: MacroDefKind::Declarative,
868 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
873 // Case 2: try to resolve in legacy scope and expand macro_rules
874 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
875 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
878 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
880 self.def_collector.unexpanded_macros.push(MacroDirective {
881 module_id: self.module_id,
882 path: mac.path.clone(),
884 legacy: Some(macro_call_id),
890 // Case 3: resolve in module scope, expand during name resolution.
891 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
892 let mut path = mac.path.clone();
894 path.kind = PathKind::Super(0);
897 self.def_collector.unexpanded_macros.push(MacroDirective {
898 module_id: self.module_id,
905 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
906 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
907 for (name, macro_) in macros {
908 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
912 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
913 // FIXME: handle cfg_attr :-)
917 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
921 fn is_macro_rules(path: &ModPath) -> bool {
922 path.as_ident() == Some(&name![macro_rules])
927 use crate::{db::DefDatabase, test_db::TestDB};
929 use ra_db::{fixture::WithFixture, SourceDatabase};
933 fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
934 let mut collector = DefCollector {
937 glob_imports: FxHashMap::default(),
938 unresolved_imports: Vec::new(),
939 resolved_imports: Vec::new(),
940 unexpanded_macros: Vec::new(),
941 unexpanded_attribute_macros: Vec::new(),
942 mod_dirs: FxHashMap::default(),
943 cfg_options: &CfgOptions::default(),
949 fn do_resolve(code: &str) -> CrateDefMap {
950 let (db, _file_id) = TestDB::with_single_file(&code);
951 let krate = db.test_crate();
954 let edition = db.crate_graph().edition(krate);
955 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
956 let root = modules.alloc(ModuleData::default());
960 extern_prelude: FxHashMap::default(),
964 diagnostics: Vec::new(),
967 do_collect_defs(&db, def_map)
971 fn test_macro_expand_will_stop() {
975 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }