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;
21 item_scope::Resolution,
23 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
24 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
26 path::{ModPath, PathKind},
28 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
29 LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc,
30 TypeAliasLoc, UnionLoc,
33 pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
34 let crate_graph = db.crate_graph();
36 // populate external prelude
37 for dep in crate_graph.dependencies(def_map.krate) {
38 let dep_def_map = db.crate_def_map(dep.crate_id);
39 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
40 def_map.extern_prelude.insert(
42 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
45 // look for the prelude
46 // If the dependency defines a prelude, we overwrite an already defined
47 // prelude. This is necessary to import the "std" prelude if a crate
48 // depends on both "core" and "std".
49 let dep_def_map = db.crate_def_map(dep.crate_id);
50 if dep_def_map.prelude.is_some() {
51 def_map.prelude = dep_def_map.prelude;
55 let cfg_options = crate_graph.cfg_options(def_map.krate);
57 let mut collector = DefCollector {
60 glob_imports: FxHashMap::default(),
61 unresolved_imports: Vec::new(),
62 resolved_imports: Vec::new(),
64 unexpanded_macros: Vec::new(),
65 unexpanded_attribute_macros: Vec::new(),
66 mod_dirs: FxHashMap::default(),
73 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
74 enum PartialResolvedImport {
75 /// None of any namespaces is resolved
77 /// One of namespaces is resolved
79 /// All namespaces are resolved, OR it is came from other crate
83 impl PartialResolvedImport {
84 fn namespaces(&self) -> PerNs {
86 PartialResolvedImport::Unresolved => PerNs::none(),
87 PartialResolvedImport::Indeterminate(ns) => *ns,
88 PartialResolvedImport::Resolved(ns) => *ns,
93 #[derive(Clone, Debug, Eq, PartialEq)]
94 struct ImportDirective {
95 module_id: LocalModuleId,
96 import_id: LocalImportId,
97 import: raw::ImportData,
98 status: PartialResolvedImport,
101 #[derive(Clone, Debug, Eq, PartialEq)]
102 struct MacroDirective {
103 module_id: LocalModuleId,
104 ast_id: AstId<ast::MacroCall>,
106 legacy: Option<MacroCallId>,
109 /// Walks the tree of module recursively
110 struct DefCollector<'a, DB> {
112 def_map: CrateDefMap,
113 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
114 unresolved_imports: Vec<ImportDirective>,
115 resolved_imports: Vec<ImportDirective>,
116 unexpanded_macros: Vec<MacroDirective>,
117 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
118 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
119 cfg_options: &'a CfgOptions,
122 impl<DB> DefCollector<'_, DB>
126 fn collect(&mut self) {
127 let crate_graph = self.db.crate_graph();
128 let file_id = crate_graph.crate_root(self.def_map.krate);
129 let raw_items = self.db.raw_items(file_id.into());
130 let module_id = self.def_map.root;
131 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
133 def_collector: &mut *self,
135 file_id: file_id.into(),
136 raw_items: &raw_items,
137 mod_dir: ModDir::root(),
139 .collect(raw_items.items());
141 // main name resolution fixed-point loop.
144 self.db.check_canceled();
145 self.resolve_imports();
147 match self.resolve_macros() {
148 ReachedFixedPoint::Yes => break,
149 ReachedFixedPoint::No => i += 1,
152 log::error!("name resolution is stuck");
157 // Resolve all indeterminate resolved imports again
158 // As some of the macros will expand newly import shadowing partial resolved imports
159 // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports`
161 let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
162 if let PartialResolvedImport::Indeterminate(_) = directive.status {
163 let mut directive = directive.clone();
164 directive.status = PartialResolvedImport::Unresolved;
170 self.unresolved_imports.extend(partial_resolved);
171 self.resolve_imports();
173 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
174 // show unresolved imports in completion, etc
175 for directive in unresolved_imports {
176 self.record_resolved_import(&directive)
180 /// Define a macro with `macro_rules`.
182 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
183 /// then it is also defined in the root module scope.
184 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
186 /// It is surprising that the macro will never be in the current module scope.
187 /// These code fails with "unresolved import/macro",
188 /// ```rust,compile_fail
189 /// mod m { macro_rules! foo { () => {} } }
190 /// use m::foo as bar;
193 /// ```rust,compile_fail
194 /// macro_rules! foo { () => {} }
199 /// Well, this code compiles, because the plain path `foo` in `use` is searched
200 /// in the legacy textual scope only.
202 /// macro_rules! foo { () => {} }
207 module_id: LocalModuleId,
213 self.define_legacy_macro(module_id, name.clone(), macro_);
216 // In Rust, `#[macro_export]` macros are unconditionally visible at the
217 // crate root, even if the parent modules is **not** visible.
222 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
227 /// Define a legacy textual scoped macro in module
229 /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module.
230 /// It will clone all macros from parent legacy scope, whose definition is prior to
231 /// the definition of current module.
232 /// And also, `macro_use` on a module will import all legacy macros visable inside to
233 /// current legacy scope, with possible shadowing.
234 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
236 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
239 /// Import macros from `#[macro_use] extern crate`.
240 fn import_macros_from_extern_crate(
242 current_module_id: LocalModuleId,
243 import: &raw::ImportData,
246 "importing macros from extern crate: {:?} ({:?})",
248 self.def_map.edition,
251 let res = self.def_map.resolve_name_in_extern_prelude(
255 .expect("extern crate should have been desugared to one-element path"),
258 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
259 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
260 self.import_all_macros_exported(current_module_id, m.krate);
264 /// Import all exported macros from another crate
266 /// Exported macros are just all macros in the root module scope.
267 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
268 /// created by `use` in the root module, ignoring the visibility of `use`.
269 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
270 let def_map = self.db.crate_def_map(krate);
271 for (name, def) in def_map[def_map.root].scope.macros() {
272 // `macro_use` only bring things into legacy scope.
273 self.define_legacy_macro(current_module_id, name.clone(), def);
277 /// Import resolution
279 /// This is a fix point algorithm. We resolve imports until no forward
280 /// progress in resolving imports is made
281 fn resolve_imports(&mut self) {
282 let mut n_previous_unresolved = self.unresolved_imports.len() + 1;
284 while self.unresolved_imports.len() < n_previous_unresolved {
285 n_previous_unresolved = self.unresolved_imports.len();
286 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
287 for mut directive in imports {
288 directive.status = self.resolve_import(directive.module_id, &directive.import);
290 match directive.status {
291 PartialResolvedImport::Indeterminate(_) => {
292 self.record_resolved_import(&directive);
293 // FIXME: For avoid performance regression,
294 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
295 self.resolved_imports.push(directive)
297 PartialResolvedImport::Resolved(_) => {
298 self.record_resolved_import(&directive);
299 self.resolved_imports.push(directive)
301 PartialResolvedImport::Unresolved => {
302 self.unresolved_imports.push(directive);
311 module_id: LocalModuleId,
312 import: &raw::ImportData,
313 ) -> PartialResolvedImport {
314 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
315 if import.is_extern_crate {
316 let res = self.def_map.resolve_name_in_extern_prelude(
320 .expect("extern crate should have been desugared to one-element path"),
322 PartialResolvedImport::Resolved(res)
324 let res = self.def_map.resolve_path_fp_with_macro(
329 BuiltinShadowMode::Module,
332 let def = res.resolved_def;
333 if res.reached_fixedpoint == ReachedFixedPoint::No {
334 return PartialResolvedImport::Unresolved;
337 if let Some(krate) = res.krate {
338 if krate != self.def_map.krate {
339 return PartialResolvedImport::Resolved(def);
343 // Check whether all namespace is resolved
344 if def.take_types().is_some()
345 && def.take_values().is_some()
346 && def.take_macros().is_some()
348 PartialResolvedImport::Resolved(def)
350 PartialResolvedImport::Indeterminate(def)
355 fn record_resolved_import(&mut self, directive: &ImportDirective) {
356 let module_id = directive.module_id;
357 let import_id = directive.import_id;
358 let import = &directive.import;
359 let def = directive.status.namespaces();
362 log::debug!("glob import: {:?}", import);
363 match def.take_types() {
364 Some(ModuleDefId::ModuleId(m)) => {
365 if import.is_prelude {
366 tested_by!(std_prelude);
367 self.def_map.prelude = Some(m);
368 } else if m.krate != self.def_map.krate {
369 tested_by!(glob_across_crates);
370 // glob import from other crate => we can just import everything once
371 let item_map = self.db.crate_def_map(m.krate);
372 let scope = &item_map[m.local_id].scope;
374 // Module scoped macros is included
378 .map(|(name, res)| (name.clone(), res.clone()))
379 .collect::<Vec<_>>();
381 self.update(module_id, Some(import_id), &items);
383 // glob import from same crate => we do an initial
384 // import, and then need to propagate any further
386 let scope = &self.def_map[m.local_id].scope;
388 // Module scoped macros is included
392 .map(|(name, res)| (name.clone(), res.clone()))
393 .collect::<Vec<_>>();
395 self.update(module_id, Some(import_id), &items);
396 // record the glob import in case we add further items
397 let glob = self.glob_imports.entry(m.local_id).or_default();
398 if !glob.iter().any(|it| *it == (module_id, import_id)) {
399 glob.push((module_id, import_id));
403 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
404 tested_by!(glob_enum);
405 // glob import from enum => just import all the variants
406 let enum_data = self.db.enum_data(e);
407 let resolutions = enum_data
410 .filter_map(|(local_id, variant_data)| {
411 let name = variant_data.name.clone();
412 let variant = EnumVariantId { parent: e, local_id };
413 let res = Resolution {
414 def: PerNs::both(variant.into(), variant.into()),
415 import: Some(import_id),
419 .collect::<Vec<_>>();
420 self.update(module_id, Some(import_id), &resolutions);
423 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
426 log::debug!("glob import {:?} didn't resolve as type", import);
430 match import.path.segments.last() {
431 Some(last_segment) => {
432 let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
433 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
435 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
436 if import.is_extern_crate && module_id == self.def_map.root {
437 if let Some(def) = def.take_types() {
438 self.def_map.extern_prelude.insert(name.clone(), def);
442 let resolution = Resolution { def, import: Some(import_id) };
443 self.update(module_id, Some(import_id), &[(name, resolution)]);
445 None => tested_by!(bogus_paths),
452 module_id: LocalModuleId,
453 import: Option<LocalImportId>,
454 resolutions: &[(Name, Resolution)],
456 self.update_recursive(module_id, import, resolutions, 0)
461 module_id: LocalModuleId,
462 import: Option<LocalImportId>,
463 resolutions: &[(Name, Resolution)],
467 // prevent stack overflows (but this shouldn't be possible)
468 panic!("infinite recursion in glob imports!");
470 let module_items = &mut self.def_map.modules[module_id].scope;
471 let mut changed = false;
472 for (name, res) in resolutions {
473 let existing = module_items.items.entry(name.clone()).or_default();
475 if existing.def.types.is_none() && res.def.types.is_some() {
476 existing.def.types = res.def.types;
477 existing.import = import.or(res.import);
480 if existing.def.values.is_none() && res.def.values.is_some() {
481 existing.def.values = res.def.values;
482 existing.import = import.or(res.import);
485 if existing.def.macros.is_none() && res.def.macros.is_some() {
486 existing.def.macros = res.def.macros;
487 existing.import = import.or(res.import);
491 if existing.def.is_none()
493 && existing.import.is_none()
494 && res.import.is_some()
496 existing.import = res.import;
503 let glob_imports = self
507 .flat_map(|v| v.iter())
509 .collect::<Vec<_>>();
510 for (glob_importing_module, glob_import) in glob_imports {
511 // We pass the glob import so that the tracked import in those modules is that glob import
512 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
516 fn resolve_macros(&mut self) -> ReachedFixedPoint {
517 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
518 let mut attribute_macros =
519 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
520 let mut resolved = Vec::new();
521 let mut res = ReachedFixedPoint::Yes;
522 macros.retain(|directive| {
523 if let Some(call_id) = directive.legacy {
524 res = ReachedFixedPoint::No;
525 resolved.push((directive.module_id, call_id));
529 let resolved_res = self.def_map.resolve_path_fp_with_macro(
534 BuiltinShadowMode::Module,
537 if let Some(def) = resolved_res.resolved_def.take_macros() {
538 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
539 resolved.push((directive.module_id, call_id));
540 res = ReachedFixedPoint::No;
546 attribute_macros.retain(|(module_id, ast_id, path)| {
547 let resolved_res = self.resolve_attribute_macro(path);
549 if let Some(def) = resolved_res {
550 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
551 resolved.push((*module_id, call_id));
552 res = ReachedFixedPoint::No;
559 self.unexpanded_macros = macros;
560 self.unexpanded_attribute_macros = attribute_macros;
562 for (module_id, macro_call_id) in resolved {
563 self.collect_macro_expansion(module_id, macro_call_id);
569 fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
570 // FIXME this is currently super hacky, just enough to support the
572 if let Some(name) = path.as_ident() {
573 // FIXME this should actually be handled with the normal name
574 // resolution; the std lib defines built-in stubs for the derives,
575 // but these are new-style `macro`s, which we don't support yet
576 if let Some(def_id) = find_builtin_derive(name) {
583 fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
584 let file_id: HirFileId = macro_call_id.as_file();
585 let raw_items = self.db.raw_items(file_id);
586 let mod_dir = self.mod_dirs[&module_id].clone();
588 def_collector: &mut *self,
591 raw_items: &raw_items,
594 .collect(raw_items.items());
597 fn finish(self) -> CrateDefMap {
602 /// Walks a single module, populating defs, imports and macros
603 struct ModCollector<'a, D> {
605 module_id: LocalModuleId,
607 raw_items: &'a raw::RawItems,
611 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
615 fn collect(&mut self, items: &[raw::RawItem]) {
616 // Note: don't assert that inserted value is fresh: it's simply not true
618 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
620 // Prelude module is always considered to be `#[macro_use]`.
621 if let Some(prelude_module) = self.def_collector.def_map.prelude {
622 if prelude_module.krate != self.def_collector.def_map.krate {
623 tested_by!(prelude_is_macro_use);
624 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
628 // This should be processed eagerly instead of deferred to resolving.
629 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
632 if self.is_cfg_enabled(&item.attrs) {
633 if let raw::RawItemKind::Import(import_id) = item.kind {
634 let import = self.raw_items[import_id].clone();
635 if import.is_extern_crate && import.is_macro_use {
636 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
643 if self.is_cfg_enabled(&item.attrs) {
645 raw::RawItemKind::Module(m) => {
646 self.collect_module(&self.raw_items[m], &item.attrs)
648 raw::RawItemKind::Import(import_id) => {
649 self.def_collector.unresolved_imports.push(ImportDirective {
650 module_id: self.module_id,
652 import: self.raw_items[import_id].clone(),
653 status: PartialResolvedImport::Unresolved,
656 raw::RawItemKind::Def(def) => {
657 self.define_def(&self.raw_items[def], &item.attrs)
659 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
660 raw::RawItemKind::Impl(imp) => {
661 let module = ModuleId {
662 krate: self.def_collector.def_map.krate,
663 local_id: self.module_id,
665 let container = ContainerId::ModuleId(module);
666 let ast_id = self.raw_items[imp].ast_id;
668 ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
669 .intern(self.def_collector.db);
670 self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id)
677 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
678 let path_attr = attrs.by_key("path").string_value();
679 let is_macro_use = attrs.by_key("macro_use").exists();
681 // inline module, just recurse
682 raw::ModuleData::Definition { name, items, ast_id } => {
684 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
687 def_collector: &mut *self.def_collector,
689 file_id: self.file_id,
690 raw_items: self.raw_items,
691 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
695 self.import_all_legacy_macros(module_id);
698 // out of line module, resolve, parse and recurse
699 raw::ModuleData::Declaration { name, ast_id } => {
700 let ast_id = AstId::new(self.file_id, *ast_id);
701 match self.mod_dir.resolve_declaration(
702 self.def_collector.db,
707 Ok((file_id, mod_dir)) => {
708 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
709 let raw_items = self.def_collector.db.raw_items(file_id.into());
711 def_collector: &mut *self.def_collector,
713 file_id: file_id.into(),
714 raw_items: &raw_items,
717 .collect(raw_items.items());
719 self.import_all_legacy_macros(module_id);
722 Err(candidate) => self.def_collector.def_map.diagnostics.push(
723 DefDiagnostic::UnresolvedModule {
724 module: self.module_id,
734 fn push_child_module(
737 declaration: AstId<ast::Module>,
738 definition: Option<FileId>,
740 let modules = &mut self.def_collector.def_map.modules;
741 let res = modules.alloc(ModuleData::default());
742 modules[res].parent = Some(self.module_id);
743 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
744 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
745 modules[self.module_id].children.insert(name.clone(), res);
746 let resolution = Resolution {
748 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
752 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
756 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
757 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
758 // FIXME: check attrs to see if this is an attribute macro invocation;
759 // in which case we don't add the invocation, just a single attribute
762 self.collect_derives(attrs, def);
764 let name = def.name.clone();
765 let container = ContainerId::ModuleId(module);
766 let def: PerNs = match def.kind {
767 raw::DefKind::Function(ast_id) => {
768 let def = FunctionLoc {
769 container: container.into(),
770 ast_id: AstId::new(self.file_id, ast_id),
772 .intern(self.def_collector.db);
774 PerNs::values(def.into())
776 raw::DefKind::Struct(ast_id) => {
777 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
778 .intern(self.def_collector.db);
779 PerNs::both(def.into(), def.into())
781 raw::DefKind::Union(ast_id) => {
782 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
783 .intern(self.def_collector.db);
784 PerNs::both(def.into(), def.into())
786 raw::DefKind::Enum(ast_id) => {
787 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
788 .intern(self.def_collector.db);
789 PerNs::types(def.into())
791 raw::DefKind::Const(ast_id) => {
793 container: container.into(),
794 ast_id: AstId::new(self.file_id, ast_id),
796 .intern(self.def_collector.db);
798 PerNs::values(def.into())
800 raw::DefKind::Static(ast_id) => {
801 let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
802 .intern(self.def_collector.db);
804 PerNs::values(def.into())
806 raw::DefKind::Trait(ast_id) => {
807 let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
808 .intern(self.def_collector.db);
810 PerNs::types(def.into())
812 raw::DefKind::TypeAlias(ast_id) => {
813 let def = TypeAliasLoc {
814 container: container.into(),
815 ast_id: AstId::new(self.file_id, ast_id),
817 .intern(self.def_collector.db);
819 PerNs::types(def.into())
822 let resolution = Resolution { def, import: None };
823 self.def_collector.update(self.module_id, None, &[(name, resolution)])
826 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
827 for derive_subtree in attrs.by_key("derive").tt_values() {
828 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
829 for tt in &derive_subtree.token_trees {
830 let ident = match &tt {
831 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
832 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
833 _ => continue, // anything else would be an error (which we currently ignore)
835 let path = ModPath::from_tt_ident(ident);
837 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
838 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
843 fn collect_macro(&mut self, mac: &raw::MacroData) {
844 let ast_id = AstId::new(self.file_id, mac.ast_id);
846 // Case 0: builtin macros
848 if let Some(name) = &mac.name {
849 let krate = self.def_collector.def_map.krate;
850 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
851 self.def_collector.define_macro(
862 // Case 1: macro rules, define a macro in crate-global mutable scope
863 if is_macro_rules(&mac.path) {
864 if let Some(name) = &mac.name {
865 let macro_id = MacroDefId {
866 ast_id: Some(ast_id),
867 krate: Some(self.def_collector.def_map.krate),
868 kind: MacroDefKind::Declarative,
870 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
875 // Case 2: try to resolve in legacy scope and expand macro_rules
876 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
877 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
880 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
882 self.def_collector.unexpanded_macros.push(MacroDirective {
883 module_id: self.module_id,
884 path: mac.path.clone(),
886 legacy: Some(macro_call_id),
892 // Case 3: resolve in module scope, expand during name resolution.
893 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
894 let mut path = mac.path.clone();
896 path.kind = PathKind::Super(0);
899 self.def_collector.unexpanded_macros.push(MacroDirective {
900 module_id: self.module_id,
907 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
908 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
909 for (name, macro_) in macros {
910 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
914 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
915 // FIXME: handle cfg_attr :-)
919 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
923 fn is_macro_rules(path: &ModPath) -> bool {
924 path.as_ident() == Some(&name![macro_rules])
929 use crate::{db::DefDatabase, test_db::TestDB};
931 use ra_db::{fixture::WithFixture, SourceDatabase};
935 fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
936 let mut collector = DefCollector {
939 glob_imports: FxHashMap::default(),
940 unresolved_imports: Vec::new(),
941 resolved_imports: Vec::new(),
942 unexpanded_macros: Vec::new(),
943 unexpanded_attribute_macros: Vec::new(),
944 mod_dirs: FxHashMap::default(),
945 cfg_options: &CfgOptions::default(),
951 fn do_resolve(code: &str) -> CrateDefMap {
952 let (db, _file_id) = TestDB::with_single_file(&code);
953 let krate = db.test_crate();
956 let edition = db.crate_graph().edition(krate);
957 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
958 let root = modules.alloc(ModuleData::default());
962 extern_prelude: FxHashMap::default(),
966 diagnostics: Vec::new(),
969 do_collect_defs(&db, def_map)
973 fn test_macro_expand_will_stop() {
977 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }