1use std::{iter, mem};
7
8use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin};
9use cfg::{CfgAtom, CfgExpr, CfgOptions};
10use either::Either;
11use hir_expand::{
12 AttrMacroAttrIds, EditionedFileId, ErasedAstId, ExpandTo, HirFileId, InFile, MacroCallId,
13 MacroCallKind, MacroDefId, MacroDefKind,
14 attrs::{Attr, AttrId},
15 builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro},
16 mod_path::{ModPath, PathKind},
17 name::{AsName, Name},
18 proc_macro::CustomProcMacroExpander,
19};
20use intern::{Interned, sym};
21use itertools::izip;
22use la_arena::Idx;
23use rustc_hash::{FxHashMap, FxHashSet};
24use smallvec::SmallVec;
25use span::{Edition, FileAstId, SyntaxContext};
26use syntax::ast;
27use triomphe::Arc;
28
29use crate::{
30 AdtId, AssocItemId, AstId, AstIdWithPath, ConstLoc, EnumLoc, ExternBlockLoc, ExternCrateId,
31 ExternCrateLoc, FunctionId, FunctionLoc, FxIndexMap, ImplLoc, Intern, ItemContainerId, Lookup,
32 Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags,
33 ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc,
34 UnionLoc, UnresolvedMacro, UseId, UseLoc,
35 db::DefDatabase,
36 item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
37 item_tree::{
38 self, Attrs, AttrsOrCfg, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId,
39 Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId,
40 },
41 macro_call_as_call_id,
42 nameres::{
43 BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
44 assoc::TraitItems,
45 attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
46 crate_def_map,
47 diagnostics::DefDiagnostic,
48 mod_resolution::ModDir,
49 path_resolution::{ReachedFixedPoint, ResolvePathResult},
50 proc_macro::{ProcMacroDef, ProcMacroKind, parse_macro_name_and_helper_attrs},
51 sub_namespace_match,
52 },
53 per_ns::{Item, PerNs},
54 tt,
55 visibility::{RawVisibility, Visibility},
56};
57
58const GLOB_RECURSION_LIMIT: usize = 100;
59const FIXED_POINT_LIMIT: usize = 8192;
60
61pub(super) fn collect_defs(
62 db: &dyn DefDatabase,
63 def_map: DefMap,
64 tree_id: TreeId,
65 crate_local_def_map: Option<&LocalDefMap>,
66) -> (DefMap, LocalDefMap) {
67 let krate = &def_map.krate.data(db);
68 let cfg_options = def_map.krate.cfg_options(db);
69
70 let mut deps =
72 FxIndexMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
73 for dep in &krate.dependencies {
74 tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
75
76 deps.insert(dep.as_name(), dep.clone());
77 }
78
79 let proc_macros = if krate.is_proc_macro {
80 db.proc_macros_for_crate(def_map.krate)
81 .and_then(|proc_macros| {
82 proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition))
83 })
84 .unwrap_or_default()
85 } else {
86 Default::default()
87 };
88
89 let mut collector = DefCollector {
90 db,
91 def_map,
92 local_def_map: LocalDefMap::default(),
93 crate_local_def_map,
94 deps,
95 glob_imports: FxHashMap::default(),
96 unresolved_imports: Vec::new(),
97 indeterminate_imports: Vec::new(),
98 unresolved_macros: Vec::new(),
99 mod_dirs: FxHashMap::default(),
100 cfg_options,
101 proc_macros,
102 from_glob_import: Default::default(),
103 skip_attrs: Default::default(),
104 prev_active_attrs: Default::default(),
105 unresolved_extern_crates: Default::default(),
106 is_proc_macro: krate.is_proc_macro,
107 };
108 if tree_id.is_block() {
109 collector.seed_with_inner(tree_id);
110 } else {
111 collector.seed_with_top_level();
112 }
113 collector.collect();
114 let (mut def_map, mut local_def_map) = collector.finish();
115 def_map.shrink_to_fit();
116 local_def_map.shrink_to_fit();
117 (def_map, local_def_map)
118}
119
120#[derive(Copy, Clone, Debug, Eq, PartialEq)]
121enum PartialResolvedImport {
122 Unresolved,
124 Indeterminate(PerNs),
126 Resolved(PerNs),
128}
129
130impl PartialResolvedImport {
131 fn namespaces(self) -> PerNs {
132 match self {
133 PartialResolvedImport::Unresolved => PerNs::none(),
134 PartialResolvedImport::Indeterminate(ns) | PartialResolvedImport::Resolved(ns) => ns,
135 }
136 }
137}
138
139#[derive(Clone, Debug, Eq, PartialEq)]
140struct ImportSource {
141 use_tree: Idx<ast::UseTree>,
142 id: UseId,
143 is_prelude: bool,
144 kind: ImportKind,
145}
146
147#[derive(Debug, Eq, PartialEq)]
148struct Import {
149 path: ModPath,
150 alias: Option<ImportAlias>,
151 visibility: RawVisibility,
152 source: ImportSource,
153}
154
155impl Import {
156 fn from_use(
157 tree: &ItemTree,
158 item: FileAstId<ast::Use>,
159 id: UseId,
160 is_prelude: bool,
161 mut cb: impl FnMut(Self),
162 ) {
163 let it = &tree[item];
164 let visibility = &tree[it.visibility];
165 it.expand(|idx, path, kind, alias| {
166 cb(Self {
167 path,
168 alias,
169 visibility: visibility.clone(),
170 source: ImportSource { use_tree: idx, id, is_prelude, kind },
171 });
172 });
173 }
174}
175
176#[derive(Debug, Eq, PartialEq)]
177struct ImportDirective {
178 module_id: ModuleId,
180 import: Import,
181 status: PartialResolvedImport,
182}
183
184#[derive(Clone, Debug, Eq, PartialEq)]
185struct MacroDirective<'db> {
186 module_id: ModuleId,
187 depth: usize,
188 kind: MacroDirectiveKind<'db>,
189 container: ItemContainerId,
190}
191
192#[derive(Clone, Debug, Eq, PartialEq)]
193enum MacroDirectiveKind<'db> {
194 FnLike {
195 ast_id: AstIdWithPath<ast::MacroCall>,
196 expand_to: ExpandTo,
197 ctxt: SyntaxContext,
198 },
199 Derive {
200 ast_id: AstIdWithPath<ast::Adt>,
201 derive_attr: AttrId,
202 derive_pos: usize,
203 ctxt: SyntaxContext,
204 derive_macro_id: MacroCallId,
206 },
207 Attr {
208 ast_id: AstIdWithPath<ast::Item>,
209 attr_id: AttrId,
210 attr: Attr,
211 mod_item: ModItemId,
212 tree: TreeId,
213 item_tree: &'db ItemTree,
214 },
215}
216
217struct DefCollector<'db> {
219 db: &'db dyn DefDatabase,
220 def_map: DefMap,
221 local_def_map: LocalDefMap,
222 crate_local_def_map: Option<&'db LocalDefMap>,
224 deps: FxIndexMap<Name, BuiltDependency>,
226 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, Visibility, GlobId)>>,
227 unresolved_imports: Vec<ImportDirective>,
228 indeterminate_imports: Vec<(ImportDirective, PerNs)>,
229 unresolved_macros: Vec<MacroDirective<'db>>,
230 unresolved_extern_crates: FxHashSet<Name>,
234 mod_dirs: FxHashMap<ModuleId, ModDir>,
235 cfg_options: &'db CfgOptions,
236 proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>,
241 is_proc_macro: bool,
242 from_glob_import: PerNsGlobImports,
243 skip_attrs: FxHashMap<AstId<ast::Item>, AttrId>,
251 prev_active_attrs: FxHashMap<AstId<ast::Item>, SmallVec<[AttrId; 1]>>,
255}
256
257impl<'db> DefCollector<'db> {
258 fn seed_with_top_level(&mut self) {
259 let _p = tracing::info_span!("seed_with_top_level").entered();
260
261 let file_id = self.def_map.krate.root_file_id(self.db);
262 let item_tree = self.db.file_item_tree(file_id.into());
263 let attrs = match item_tree.top_level_attrs() {
264 AttrsOrCfg::Enabled { attrs } => attrs.as_ref(),
265 AttrsOrCfg::CfgDisabled(it) => it.1.as_ref(),
266 };
267 let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
268
269 for attr in &*attrs {
271 let Some(attr_name) = attr.path.as_ident() else { continue };
272
273 match () {
274 () if *attr_name == sym::recursion_limit => {
275 if let Some(limit) = attr.string_value()
276 && let Ok(limit) = limit.as_str().parse()
277 {
278 crate_data.recursion_limit = Some(limit);
279 }
280 }
281 () if *attr_name == sym::crate_type => {
282 if attr.string_value() == Some(&sym::proc_dash_macro) {
283 self.is_proc_macro = true;
284 }
285 }
286 () if *attr_name == sym::no_core => crate_data.no_core = true,
287 () if *attr_name == sym::no_std => crate_data.no_std = true,
288 () if *attr_name == sym::rustc_coherence_is_core => {
289 crate_data.rustc_coherence_is_core = true;
290 }
291 () if *attr_name == sym::feature => {
292 let features =
293 attr.parse_path_comma_token_tree(self.db).into_iter().flatten().filter_map(
294 |(feat, _, _)| match feat.segments() {
295 [name] => Some(name.symbol().clone()),
296 _ => None,
297 },
298 );
299 crate_data.unstable_features.extend(features);
300 }
301 () if *attr_name == sym::register_tool => {
302 if let Some(ident) = attr.single_ident_value() {
303 crate_data.registered_tools.push(ident.sym.clone());
304 cov_mark::hit!(register_tool);
305 }
306 }
307 () => (),
308 }
309 }
310
311 for (name, dep) in &self.deps {
312 if dep.is_prelude() {
314 let skip = dep.is_sysroot()
328 && match dep.crate_id.data(self.db).origin {
329 CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
330 CrateOrigin::Lang(LangCrateOrigin::Std) => {
331 crate_data.no_core || crate_data.no_std
332 }
333 _ => false,
334 };
335 if skip {
336 continue;
337 }
338
339 self.local_def_map.extern_prelude.insert(
344 name.clone(),
345 (crate_def_map(self.db, dep.crate_id).root_module_id(), None),
346 );
347 }
348 }
349
350 self.inject_prelude();
351
352 if matches!(item_tree.top_level_attrs(), AttrsOrCfg::CfgDisabled(_)) {
353 return;
354 }
355
356 let module_id = self.def_map.root;
357 ModCollector {
358 def_collector: self,
359 macro_depth: 0,
360 module_id,
361 tree_id: TreeId::new(file_id.into(), None),
362 item_tree,
363 mod_dir: ModDir::root(),
364 }
365 .collect_in_top_module(item_tree.top_level_items());
366 Arc::get_mut(&mut self.def_map.data).unwrap().shrink_to_fit();
367 }
368
369 fn seed_with_inner(&mut self, tree_id: TreeId) {
370 let item_tree = tree_id.item_tree(self.db);
371 let is_cfg_enabled = matches!(item_tree.top_level_attrs(), AttrsOrCfg::Enabled { .. });
372 if is_cfg_enabled {
373 self.inject_prelude();
374
375 let module_id = self.def_map.root;
376 ModCollector {
377 def_collector: self,
378 macro_depth: 0,
379 module_id,
380 tree_id,
381 item_tree,
382 mod_dir: ModDir::root(),
383 }
384 .collect_in_top_module(item_tree.top_level_items());
385 }
386 }
387
388 fn resolution_loop(&mut self) {
389 let _p = tracing::info_span!("DefCollector::resolution_loop").entered();
390
391 let mut i = 0;
393 'resolve_attr: loop {
394 let _p = tracing::info_span!("resolve_macros loop").entered();
395 'resolve_macros: loop {
396 self.db.unwind_if_revision_cancelled();
397
398 {
399 let _p = tracing::info_span!("resolve_imports loop").entered();
400
401 'resolve_imports: loop {
402 if self.resolve_imports() == ReachedFixedPoint::Yes {
403 break 'resolve_imports;
404 }
405 }
406 }
407 if self.resolve_macros() == ReachedFixedPoint::Yes {
408 break 'resolve_macros;
409 }
410
411 i += 1;
412 if i > FIXED_POINT_LIMIT {
413 tracing::error!("name resolution is stuck");
414 break 'resolve_attr;
415 }
416 }
417
418 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
419 break 'resolve_attr;
420 }
421 }
422 }
423
424 fn collect(&mut self) {
425 let _p = tracing::info_span!("DefCollector::collect").entered();
426
427 self.resolution_loop();
428
429 let unresolved_imports = mem::take(&mut self.unresolved_imports);
430 for directive in &unresolved_imports {
432 self.record_resolved_import(directive);
433 }
434 self.unresolved_imports = unresolved_imports;
435
436 if self.is_proc_macro {
437 let module_id = self.def_map.root_module_id();
443 let root = &mut self.def_map.modules[module_id];
444 root.scope.censor_non_proc_macros(self.def_map.krate);
445 }
446 }
447
448 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
458 cov_mark::hit!(unresolved_attribute_fallback);
459
460 let unresolved_attr =
461 self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
462 .kind
463 {
464 MacroDirectiveKind::Attr { ast_id, mod_item, attr_id, attr, tree, item_tree } => {
465 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
466 directive.module_id,
467 MacroCallKind::Attr {
468 ast_id: ast_id.ast_id,
469 attr_args: None,
470 censored_attr_ids: AttrMacroAttrIds::from_one(*attr_id),
471 },
472 (*attr.path).clone(),
473 ));
474
475 self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), *attr_id);
476
477 Some((idx, directive, *mod_item, *tree, *item_tree))
478 }
479 _ => None,
480 });
481
482 match unresolved_attr {
483 Some((
484 pos,
485 &MacroDirective { module_id, depth, container, .. },
486 mod_item,
487 tree_id,
488 item_tree,
489 )) => {
490 let mod_dir = self.mod_dirs[&module_id].clone();
492 ModCollector {
493 def_collector: self,
494 macro_depth: depth,
495 module_id,
496 tree_id,
497 item_tree,
498 mod_dir,
499 }
500 .collect(&[mod_item], container);
501
502 self.unresolved_macros.swap_remove(pos);
503 ReachedFixedPoint::No
505 }
506 None => ReachedFixedPoint::Yes,
507 }
508 }
509
510 fn inject_prelude(&mut self) {
511 if self.def_map.data.no_core {
514 return;
516 }
517
518 let krate = if self.def_map.data.no_std {
519 Name::new_symbol_root(sym::core)
520 } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std) {
521 Name::new_symbol_root(sym::std)
522 } else {
523 Name::new_symbol_root(sym::core)
526 };
527
528 let edition = match self.def_map.data.edition {
529 Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015),
530 Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018),
531 Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021),
532 Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024),
533 };
534
535 let path_kind = match self.def_map.data.edition {
536 Edition::Edition2015 => PathKind::Plain,
537 _ => PathKind::Abs,
538 };
539 let path = ModPath::from_segments(
540 path_kind,
541 [krate, Name::new_symbol_root(sym::prelude), edition],
542 );
543
544 let (per_ns, _) = self.def_map.resolve_path(
545 self.crate_local_def_map.unwrap_or(&self.local_def_map),
546 self.db,
547 self.def_map.root_module_id(),
548 &path,
549 BuiltinShadowMode::Other,
550 None,
551 );
552
553 match per_ns.types {
554 Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
555 self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
556 }
557 types => {
558 tracing::debug!(
559 "could not resolve prelude path `{}` to module (resolved to {:?})",
560 path.display(self.db, Edition::LATEST),
561 types
562 );
563 }
564 }
565 }
566
567 fn local_def_map(&mut self) -> &LocalDefMap {
568 self.crate_local_def_map.unwrap_or(&self.local_def_map)
569 }
570
571 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>, fn_id: FunctionId) {
588 let kind = def.kind.to_basedb_kind();
589 let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) {
590 Some(_)
591 if kind == hir_expand::proc_macro::ProcMacroKind::Attr
592 && !self.db.expand_proc_attr_macros() =>
593 {
594 (CustomProcMacroExpander::disabled_proc_attr(), kind)
595 }
596 Some(&(_, _, true)) => (CustomProcMacroExpander::disabled(), kind),
597 Some(&(_, expander, false)) => (expander, kind),
598 None => (CustomProcMacroExpander::missing_expander(), kind),
599 };
600
601 let proc_macro_id = ProcMacroLoc {
602 container: self.def_map.root_module_id(),
603 id: ast_id,
604 expander,
605 kind,
606 edition: self.def_map.data.edition,
607 }
608 .intern(self.db);
609
610 self.def_map.macro_def_to_macro_id.insert(ast_id.erase(), proc_macro_id.into());
611 self.define_proc_macro(def.name.clone(), proc_macro_id);
612 let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
613 if let ProcMacroKind::Derive { helpers } = def.kind {
614 crate_data.exported_derives.insert(proc_macro_id.into(), helpers);
615 }
616 crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
617 }
618
619 fn define_macro_rules(
645 &mut self,
646 module_id: ModuleId,
647 name: Name,
648 macro_: MacroRulesId,
649 export: bool,
650 ) {
651 self.define_legacy_macro(module_id, name.clone(), macro_.into());
653
654 if export {
658 let module_id = self.def_map.root;
659 self.def_map.modules[module_id].scope.declare(macro_.into());
660 self.update(
661 module_id,
662 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
663 Visibility::Public,
664 None,
665 );
666 }
667 }
668
669 fn define_legacy_macro(&mut self, module_id: ModuleId, name: Name, mac: MacroId) {
677 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
679 }
680
681 fn define_macro_def(
685 &mut self,
686 module_id: ModuleId,
687 name: Name,
688 macro_: Macro2Id,
689 vis: &RawVisibility,
690 ) {
691 let vis = self
692 .def_map
693 .resolve_visibility(
694 self.crate_local_def_map.unwrap_or(&self.local_def_map),
695 self.db,
696 module_id,
697 vis,
698 false,
699 )
700 .unwrap_or(Visibility::Public);
701 self.def_map.modules[module_id].scope.declare(macro_.into());
702 self.update(
703 module_id,
704 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
705 vis,
706 None,
707 );
708 }
709
710 fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
715 let module_id = self.def_map.root;
716 self.def_map.modules[module_id].scope.declare(macro_.into());
717 self.update(
718 module_id,
719 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
720 Visibility::Public,
721 None,
722 );
723 }
724
725 fn import_macros_from_extern_crate(
732 &mut self,
733 krate: Crate,
734 names: Option<Vec<Name>>,
735 extern_crate: Option<ExternCrateId>,
736 ) {
737 let def_map = crate_def_map(self.db, krate);
738 let root_scope = &def_map[def_map.root].scope;
741 match names {
742 Some(names) => {
743 for name in names {
744 if let Some(def) = root_scope.get(&name).take_macros() {
746 self.def_map.macro_use_prelude.insert(name, (def, extern_crate));
747 }
748 }
749 }
750 None => {
751 for (name, it) in root_scope.macros() {
752 self.def_map.macro_use_prelude.insert(name.clone(), (it.def, extern_crate));
753 }
754 }
755 }
756 }
757
758 fn resolve_imports(&mut self) -> ReachedFixedPoint {
760 let mut res = ReachedFixedPoint::Yes;
761 let imports = mem::take(&mut self.unresolved_imports);
762
763 self.unresolved_imports = imports
764 .into_iter()
765 .filter_map(|mut directive| {
766 directive.status = self.resolve_import(directive.module_id, &directive.import);
767 match directive.status {
768 PartialResolvedImport::Indeterminate(resolved) => {
769 self.record_resolved_import(&directive);
770 self.indeterminate_imports.push((directive, resolved));
771 res = ReachedFixedPoint::No;
772 None
773 }
774 PartialResolvedImport::Resolved(_) => {
775 self.record_resolved_import(&directive);
776 res = ReachedFixedPoint::No;
777 None
778 }
779 PartialResolvedImport::Unresolved => Some(directive),
780 }
781 })
782 .collect();
783
784 let mut indeterminate_imports = std::mem::take(&mut self.indeterminate_imports);
789 indeterminate_imports.retain_mut(|(directive, partially_resolved)| {
790 let partially_resolved = partially_resolved.availability();
791 directive.status = self.resolve_import(directive.module_id, &directive.import);
792 match directive.status {
793 PartialResolvedImport::Indeterminate(import)
794 if partially_resolved != import.availability() =>
795 {
796 self.record_resolved_import(directive);
797 res = ReachedFixedPoint::No;
798 false
799 }
800 PartialResolvedImport::Resolved(_) => {
801 self.record_resolved_import(directive);
802 res = ReachedFixedPoint::No;
803 false
804 }
805 _ => true,
806 }
807 });
808 self.indeterminate_imports = indeterminate_imports;
809
810 res
811 }
812
813 fn resolve_import(&self, module_id: ModuleId, import: &Import) -> PartialResolvedImport {
814 let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db, Edition::LATEST))
815 .entered();
816 tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
817 let ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info } =
818 self.def_map.resolve_path_fp_with_macro(
819 self.crate_local_def_map.unwrap_or(&self.local_def_map),
820 self.db,
821 ResolveMode::Import,
822 module_id,
823 &import.path,
824 BuiltinShadowMode::Module,
825 None, );
827
828 if reached_fixedpoint == ReachedFixedPoint::No
829 || resolved_def.is_none()
830 || segment_index.is_some()
831 {
832 return PartialResolvedImport::Unresolved;
833 }
834
835 if prefix_info.differing_crate {
836 return PartialResolvedImport::Resolved(
837 resolved_def.filter_visibility(|v| matches!(v, Visibility::Public)),
838 );
839 }
840
841 if resolved_def.is_full() {
843 PartialResolvedImport::Resolved(resolved_def)
844 } else {
845 PartialResolvedImport::Indeterminate(resolved_def)
846 }
847 }
848
849 fn record_resolved_import(&mut self, directive: &ImportDirective) {
850 let _p = tracing::info_span!("record_resolved_import").entered();
851
852 let module_id = directive.module_id;
853 let import = &directive.import;
854 let mut def = directive.status.namespaces();
855 let vis = self
856 .def_map
857 .resolve_visibility(
858 self.crate_local_def_map.unwrap_or(&self.local_def_map),
859 self.db,
860 module_id,
861 &directive.import.visibility,
862 false,
863 )
864 .unwrap_or(Visibility::Public);
865
866 match import.source {
867 ImportSource {
868 kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly),
869 id,
870 use_tree,
871 ..
872 } => {
873 let name = match &import.alias {
874 Some(ImportAlias::Alias(name)) => Some(name),
875 Some(ImportAlias::Underscore) => None,
876 None => match import.path.segments().last() {
877 Some(last_segment) => Some(last_segment),
878 None => {
879 cov_mark::hit!(bogus_paths);
880 return;
881 }
882 },
883 };
884
885 if kind == ImportKind::TypeOnly {
886 def.values = None;
887 def.macros = None;
888 }
889 let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
890 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
891
892 if let Some(def) = def.types.as_mut() {
899 let is_extern_crate_reimport_without_prefix = || {
900 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
901 return false;
902 };
903 if kind == ImportKind::Glob {
904 return false;
905 }
906 matches!(import.path.kind, PathKind::Plain | PathKind::SELF)
907 && import.path.segments().len() < 2
908 };
909 if is_extern_crate_reimport_without_prefix() {
910 def.vis = vis;
911 }
912 }
913
914 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
915 }
916 ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree, .. } => {
917 tracing::debug!("glob import: {:?}", import);
918 let glob = GlobId { use_: id, idx: use_tree };
919 match def.take_types() {
920 Some(ModuleDefId::ModuleId(m)) => {
921 if is_prelude {
922 cov_mark::hit!(std_prelude);
925 self.def_map.prelude = Some((m, Some(id)));
926 } else if m.krate(self.db) != self.def_map.krate {
927 cov_mark::hit!(glob_across_crates);
928 let scope = &m.def_map(self.db)[m].scope;
930
931 let items = scope
933 .resolutions()
934 .map(|(n, res)| {
936 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
937 })
938 .filter(|(_, res)| !res.is_none())
939 .collect::<Vec<_>>();
940
941 self.update(
942 module_id,
943 &items,
944 vis,
945 Some(ImportOrExternCrate::Glob(glob)),
946 );
947 } else {
948 let scope = if m.block(self.db) == self.def_map.block_id() {
952 &self.def_map[m].scope
953 } else {
954 &m.def_map(self.db)[m].scope
955 };
956
957 let items = scope
959 .resolutions()
960 .map(|(n, res)| {
962 (
963 n,
964 res.filter_visibility(|v| {
965 v.is_visible_from_def_map(
966 self.db,
967 &self.def_map,
968 module_id,
969 )
970 }),
971 )
972 })
973 .filter(|(_, res)| !res.is_none())
974 .collect::<Vec<_>>();
975
976 self.update(
977 module_id,
978 &items,
979 vis,
980 Some(ImportOrExternCrate::Glob(glob)),
981 );
982 let glob_imports = self.glob_imports.entry(m).or_default();
984 match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
985 None => glob_imports.push((module_id, vis, glob)),
986 Some((_, old_vis, _)) => {
987 if let Some(new_vis) = old_vis.max(self.db, vis, &self.def_map)
988 {
989 *old_vis = new_vis;
990 }
991 }
992 }
993 }
994 }
995 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
996 cov_mark::hit!(glob_enum);
997 let resolutions = e
999 .enum_variants(self.db)
1000 .variants
1001 .iter()
1002 .map(|&(variant, ref name, _)| {
1003 let res = PerNs::both(variant.into(), variant.into(), vis, None);
1004 (Some(name.clone()), res)
1005 })
1006 .collect::<Vec<_>>();
1007 self.update(
1008 module_id,
1009 &resolutions,
1010 vis,
1011 Some(ImportOrExternCrate::Glob(glob)),
1012 );
1013 }
1014 Some(ModuleDefId::TraitId(it)) => {
1015 let resolutions = if true {
1022 vec![]
1023 } else {
1024 TraitItems::query(self.db, it)
1025 .items
1026 .iter()
1027 .map(|&(ref name, variant)| {
1028 let res = match variant {
1029 AssocItemId::FunctionId(it) => {
1030 PerNs::values(it.into(), vis, None)
1031 }
1032 AssocItemId::ConstId(it) => {
1033 PerNs::values(it.into(), vis, None)
1034 }
1035 AssocItemId::TypeAliasId(it) => {
1036 PerNs::types(it.into(), vis, None)
1037 }
1038 };
1039 (Some(name.clone()), res)
1040 })
1041 .collect::<Vec<_>>()
1042 };
1043 self.update(
1044 module_id,
1045 &resolutions,
1046 vis,
1047 Some(ImportOrExternCrate::Glob(glob)),
1048 );
1049 }
1050 Some(d) => {
1051 tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
1052 }
1053 None => {
1054 tracing::debug!("glob import {:?} didn't resolve as type", import);
1055 }
1056 }
1057 }
1058 }
1059 }
1060
1061 fn update(
1062 &mut self,
1063 module_id: ModuleId,
1065 resolutions: &[(Option<Name>, PerNs)],
1066 vis: Visibility,
1068 import: Option<ImportOrExternCrate>,
1069 ) {
1070 self.update_recursive(module_id, resolutions, vis, import, 0)
1071 }
1072
1073 fn update_recursive(
1074 &mut self,
1075 module_id: ModuleId,
1077 resolutions: &[(Option<Name>, PerNs)],
1078 vis: Visibility,
1081 import: Option<ImportOrExternCrate>,
1082 depth: usize,
1083 ) {
1084 if depth > GLOB_RECURSION_LIMIT {
1085 panic!("infinite recursion in glob imports!");
1087 }
1088 let mut changed = false;
1089
1090 for (name, res) in resolutions {
1091 match name {
1092 Some(name) => {
1093 changed |=
1094 self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
1095 }
1096 None => {
1097 let (tr, import) = match res.take_types_full() {
1098 Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
1099 (tr, import)
1100 }
1101 Some(other) => {
1102 tracing::debug!("non-trait `_` import of {:?}", other);
1103 continue;
1104 }
1105 None => continue,
1106 };
1107 let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
1108 let should_update = match old_vis {
1109 None => true,
1110 Some(old_vis) => {
1111 let max_vis = old_vis.max(self.db, vis, &self.def_map).unwrap_or_else(|| {
1112 panic!("`Tr as _` imports with unrelated visibilities {old_vis:?} and {vis:?} (trait {tr:?})");
1113 });
1114
1115 if max_vis == old_vis {
1116 false
1117 } else {
1118 cov_mark::hit!(upgrade_underscore_visibility);
1119 true
1120 }
1121 }
1122 };
1123
1124 if should_update {
1125 changed = true;
1126 self.def_map.modules[module_id].scope.push_unnamed_trait(
1127 tr,
1128 vis,
1129 import.and_then(ImportOrExternCrate::import),
1130 );
1131 }
1132 }
1133 }
1134 }
1135
1136 if !changed {
1137 return;
1138 }
1139 let glob_imports = self
1140 .glob_imports
1141 .get(&module_id)
1142 .into_iter()
1143 .flatten()
1144 .filter(|(glob_importing_module, _, _)| {
1145 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
1148 })
1149 .cloned()
1150 .collect::<Vec<_>>();
1151
1152 for (glob_importing_module, glob_import_vis, glob) in glob_imports {
1153 let vis = glob_import_vis.min(self.db, vis, &self.def_map).unwrap_or(glob_import_vis);
1154 self.update_recursive(
1155 glob_importing_module,
1156 resolutions,
1157 vis,
1158 Some(ImportOrExternCrate::Glob(glob)),
1159 depth + 1,
1160 );
1161 }
1162 }
1163
1164 fn push_res_and_update_glob_vis(
1165 &mut self,
1166 module_id: ModuleId,
1167 name: &Name,
1168 mut defs: PerNs,
1169 vis: Visibility,
1170 def_import_type: Option<ImportOrExternCrate>,
1171 ) -> bool {
1172 if let Some(def) = defs.types.as_mut() {
1173 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1174 }
1175 if let Some(def) = defs.values.as_mut() {
1176 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1177 }
1178 if let Some(def) = defs.macros.as_mut() {
1179 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1180 }
1181
1182 let mut changed = false;
1183
1184 if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
1185 let prev_defs = self.def_map[module_id].scope.get(name);
1186
1187 if let Some(def) = defs.types
1191 && let Some(prev_def) = prev_defs.types
1192 && def.def == prev_def.def
1193 && self.from_glob_import.contains_type(module_id, name.clone())
1194 && def.vis != prev_def.vis
1195 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1196 {
1197 changed = true;
1198 defs.types = None;
1201 self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
1202 }
1203
1204 if let Some(def) = defs.values
1205 && let Some(prev_def) = prev_defs.values
1206 && def.def == prev_def.def
1207 && self.from_glob_import.contains_value(module_id, name.clone())
1208 && def.vis != prev_def.vis
1209 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1210 {
1211 changed = true;
1212 defs.values = None;
1214 self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
1215 }
1216
1217 if let Some(def) = defs.macros
1218 && let Some(prev_def) = prev_defs.macros
1219 && def.def == prev_def.def
1220 && self.from_glob_import.contains_macro(module_id, name.clone())
1221 && def.vis != prev_def.vis
1222 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1223 {
1224 changed = true;
1225 defs.macros = None;
1227 self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
1228 }
1229 }
1230
1231 changed |= self.def_map.modules[module_id].scope.push_res_with_import(
1232 &mut self.from_glob_import,
1233 (module_id, name.clone()),
1234 defs,
1235 def_import_type,
1236 );
1237
1238 changed
1239 }
1240
1241 fn resolve_macros(&mut self) -> ReachedFixedPoint {
1242 let mut macros = mem::take(&mut self.unresolved_macros);
1243 let mut resolved = Vec::new();
1244 let mut push_resolved = |directive: &MacroDirective<'_>, call_id| {
1245 let attr_macro_item = match &directive.kind {
1246 MacroDirectiveKind::Attr { ast_id, .. } => Some(ast_id.ast_id),
1247 MacroDirectiveKind::FnLike { .. } | MacroDirectiveKind::Derive { .. } => None,
1248 };
1249 resolved.push((
1250 directive.module_id,
1251 directive.depth,
1252 directive.container,
1253 call_id,
1254 attr_macro_item,
1255 ));
1256 };
1257
1258 #[derive(PartialEq, Eq)]
1259 enum Resolved {
1260 Yes,
1261 No,
1262 }
1263
1264 let mut eager_callback_buffer = vec![];
1265 let mut res = ReachedFixedPoint::Yes;
1266 let mut retain = |directive: &MacroDirective<'db>| {
1268 let subns = match &directive.kind {
1269 MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
1270 MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
1271 MacroSubNs::Attr
1272 }
1273 };
1274 let resolver = |path: &_| {
1275 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1276 self.crate_local_def_map.unwrap_or(&self.local_def_map),
1277 self.db,
1278 ResolveMode::Other,
1279 directive.module_id,
1280 path,
1281 BuiltinShadowMode::Module,
1282 Some(subns),
1283 );
1284 resolved_res.resolved_def.take_macros().map(|it| (it, self.db.macro_def(it)))
1285 };
1286 let resolver_def_id = |path: &_| resolver(path).map(|(_, it)| it);
1287
1288 match &directive.kind {
1289 MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1290 let call_id = macro_call_as_call_id(
1291 self.db,
1292 ast_id.ast_id,
1293 &ast_id.path,
1294 *call_site,
1295 *expand_to,
1296 self.def_map.krate,
1297 resolver_def_id,
1298 &mut |ptr, call_id| {
1299 eager_callback_buffer.push((directive.module_id, ptr, call_id));
1300 },
1301 );
1302 if let Ok(call_id) = call_id {
1303 if let Some(call_id) = call_id.value {
1305 self.def_map.modules[directive.module_id]
1306 .scope
1307 .add_macro_invoc(ast_id.ast_id, call_id);
1308
1309 push_resolved(directive, call_id);
1310
1311 res = ReachedFixedPoint::No;
1312 return Resolved::Yes;
1313 }
1314 }
1315 }
1316 MacroDirectiveKind::Derive {
1317 ast_id,
1318 derive_attr,
1319 derive_pos,
1320 ctxt: call_site,
1321 derive_macro_id,
1322 } => {
1323 let id = derive_macro_as_call_id(
1324 self.db,
1325 ast_id,
1326 *derive_attr,
1327 *derive_pos as u32,
1328 *call_site,
1329 self.def_map.krate,
1330 resolver,
1331 *derive_macro_id,
1332 );
1333
1334 if let Ok((macro_id, def_id, call_id)) = id {
1335 self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1336 ast_id.ast_id,
1337 call_id,
1338 *derive_attr,
1339 *derive_pos,
1340 );
1341 if def_id.krate != self.def_map.krate {
1343 let def_map = crate_def_map(self.db, def_id.krate);
1344 if let Some(helpers) = def_map.data.exported_derives.get(¯o_id) {
1345 self.def_map
1346 .derive_helpers_in_scope
1347 .entry(ast_id.ast_id.map(|it| it.upcast()))
1348 .or_default()
1349 .extend(izip!(
1350 helpers.iter().cloned(),
1351 iter::repeat(macro_id),
1352 iter::repeat(call_id),
1353 ));
1354 }
1355 }
1356
1357 push_resolved(directive, call_id);
1358 res = ReachedFixedPoint::No;
1359 return Resolved::Yes;
1360 }
1361 }
1362 MacroDirectiveKind::Attr {
1363 ast_id: file_ast_id,
1364 mod_item,
1365 attr_id,
1366 attr,
1367 tree,
1368 item_tree,
1369 } => {
1370 let &AstIdWithPath { ast_id, ref path } = file_ast_id;
1371 let file_id = ast_id.file_id;
1372
1373 let mut recollect_without = |collector: &mut Self| {
1374 let mod_dir = collector.mod_dirs[&directive.module_id].clone();
1376 collector
1377 .skip_attrs
1378 .insert(InFile::new(file_id, mod_item.ast_id()), *attr_id);
1379
1380 ModCollector {
1381 def_collector: collector,
1382 macro_depth: directive.depth,
1383 module_id: directive.module_id,
1384 tree_id: *tree,
1385 item_tree,
1386 mod_dir,
1387 }
1388 .collect(&[*mod_item], directive.container);
1389 res = ReachedFixedPoint::No;
1390 Resolved::Yes
1391 };
1392
1393 if let Some(ident) = path.as_ident()
1394 && let Some(helpers) = self.def_map.derive_helpers_in_scope.get(&ast_id)
1395 && helpers.iter().any(|(it, ..)| it == ident)
1396 {
1397 cov_mark::hit!(resolved_derive_helper);
1398 return recollect_without(self);
1401 }
1402
1403 let def = match resolver_def_id(path) {
1404 Some(def) if def.is_attribute() => def,
1405 _ => return Resolved::No,
1406 };
1407
1408 if matches!(
1415 def.kind,
1416 MacroDefKind::BuiltInAttr(_, expander)
1417 if expander.is_test() || expander.is_bench() || expander.is_test_case()
1418 ) {
1419 let test_is_active = self.cfg_options.check_atom(&CfgAtom::Flag(sym::test));
1420 if test_is_active {
1421 return recollect_without(self);
1422 }
1423 }
1424
1425 let mut call_id = || {
1426 let active_attrs = self.prev_active_attrs.entry(ast_id).or_default();
1427 active_attrs.push(*attr_id);
1428
1429 attr_macro_as_call_id(
1430 self.db,
1431 file_ast_id,
1432 attr,
1433 AttrMacroAttrIds::from_many(active_attrs),
1434 self.def_map.krate,
1435 def,
1436 )
1437 };
1438 if matches!(def,
1439 MacroDefId { kind: MacroDefKind::BuiltInAttr(_, exp), .. }
1440 if exp.is_derive()
1441 ) {
1442 let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
1447 ModItemId::Struct(ast_id) => ast_id.upcast(),
1448 ModItemId::Union(ast_id) => ast_id.upcast(),
1449 ModItemId::Enum(ast_id) => ast_id.upcast(),
1450 _ => {
1451 let diag = DefDiagnostic::invalid_derive_target(
1452 directive.module_id,
1453 ast_id,
1454 *attr_id,
1455 );
1456 self.def_map.diagnostics.push(diag);
1457 return recollect_without(self);
1458 }
1459 };
1460
1461 let ast_id = ast_id.with_value(ast_adt_id);
1462
1463 match attr.parse_path_comma_token_tree(self.db) {
1464 Some(derive_macros) => {
1465 let call_id = call_id();
1466 let mut len = 0;
1467 for (idx, (path, call_site, _)) in derive_macros.enumerate() {
1468 let ast_id = AstIdWithPath::new(
1469 file_id,
1470 ast_id.value,
1471 Interned::new(path),
1472 );
1473 self.unresolved_macros.push(MacroDirective {
1474 module_id: directive.module_id,
1475 depth: directive.depth + 1,
1476 kind: MacroDirectiveKind::Derive {
1477 ast_id,
1478 derive_attr: *attr_id,
1479 derive_pos: idx,
1480 ctxt: call_site.ctx,
1481 derive_macro_id: call_id,
1482 },
1483 container: directive.container,
1484 });
1485 len = idx;
1486 }
1487
1488 self.def_map.modules[directive.module_id]
1493 .scope
1494 .init_derive_attribute(ast_id, *attr_id, call_id, len + 1);
1495 }
1496 None => {
1497 let diag = DefDiagnostic::malformed_derive(
1498 directive.module_id,
1499 ast_id,
1500 *attr_id,
1501 );
1502 self.def_map.diagnostics.push(diag);
1503 }
1504 }
1505
1506 return recollect_without(self);
1507 }
1508
1509 if let MacroDefKind::ProcMacro(_, exp, _) = def.kind {
1510 if let Some(err) = exp.as_expand_error(def.krate) {
1515 self.def_map.diagnostics.push(DefDiagnostic::macro_error(
1516 directive.module_id,
1517 ast_id,
1518 (**path).clone(),
1519 err,
1520 ));
1521 return recollect_without(self);
1522 }
1523 }
1524
1525 let call_id = call_id();
1526 self.def_map.modules[directive.module_id]
1527 .scope
1528 .add_attr_macro_invoc(ast_id, call_id);
1529
1530 push_resolved(directive, call_id);
1531 res = ReachedFixedPoint::No;
1532 return Resolved::Yes;
1533 }
1534 }
1535
1536 Resolved::No
1537 };
1538 macros.retain(|it| retain(it) == Resolved::No);
1539 macros.extend(mem::take(&mut self.unresolved_macros));
1541 self.unresolved_macros = macros;
1542
1543 for (module_id, ptr, call_id) in eager_callback_buffer {
1544 self.def_map.modules[module_id].scope.add_macro_invoc(ptr.map(|(_, it)| it), call_id);
1545 }
1546
1547 for (module_id, depth, container, macro_call_id, attr_macro_item) in resolved {
1548 self.collect_macro_expansion(
1549 module_id,
1550 macro_call_id,
1551 depth,
1552 container,
1553 attr_macro_item,
1554 );
1555 }
1556
1557 res
1558 }
1559
1560 fn collect_macro_expansion(
1561 &mut self,
1562 module_id: ModuleId,
1563 macro_call_id: MacroCallId,
1564 depth: usize,
1565 container: ItemContainerId,
1566 attr_macro_item: Option<AstId<ast::Item>>,
1567 ) {
1568 if depth > self.def_map.recursion_limit() as usize {
1569 cov_mark::hit!(macro_expansion_overflow);
1570 tracing::warn!("macro expansion is too deep");
1571 return;
1572 }
1573 let file_id = macro_call_id.into();
1574
1575 let item_tree = self.db.file_item_tree(file_id);
1576
1577 if let Some(attr_macro_item) = attr_macro_item
1593 && let Some(derive_helpers) = self.def_map.derive_helpers_in_scope.get(&attr_macro_item)
1594 {
1595 let derive_helpers = derive_helpers.clone();
1596 for item in item_tree.top_level_items() {
1597 self.def_map
1598 .derive_helpers_in_scope
1599 .entry(InFile::new(file_id, item.ast_id()))
1600 .or_default()
1601 .extend(derive_helpers.iter().cloned());
1602 }
1603 }
1604
1605 let mod_dir = if macro_call_id.is_include_macro(self.db) {
1606 ModDir::root()
1607 } else {
1608 self.mod_dirs[&module_id].clone()
1609 };
1610
1611 ModCollector {
1612 def_collector: &mut *self,
1613 macro_depth: depth,
1614 tree_id: TreeId::new(file_id, None),
1615 module_id,
1616 item_tree,
1617 mod_dir,
1618 }
1619 .collect(item_tree.top_level_items(), container);
1620 }
1621
1622 fn finish(mut self) -> (DefMap, LocalDefMap) {
1623 let _p = tracing::info_span!("DefCollector::finish").entered();
1625
1626 for directive in &self.unresolved_macros {
1627 match &directive.kind {
1628 MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1629 let macro_call_as_call_id = macro_call_as_call_id(
1631 self.db,
1632 ast_id.ast_id,
1633 &ast_id.path,
1634 *call_site,
1635 *expand_to,
1636 self.def_map.krate,
1637 |path| {
1638 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1639 self.crate_local_def_map.unwrap_or(&self.local_def_map),
1640 self.db,
1641 ResolveMode::Other,
1642 directive.module_id,
1643 path,
1644 BuiltinShadowMode::Module,
1645 Some(MacroSubNs::Bang),
1646 );
1647 resolved_res.resolved_def.take_macros().map(|it| self.db.macro_def(it))
1648 },
1649 &mut |_, _| (),
1650 );
1651 if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
1652 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1653 directive.module_id,
1654 MacroCallKind::FnLike {
1655 ast_id: ast_id.ast_id,
1656 expand_to: *expand_to,
1657 eager: None,
1658 },
1659 path,
1660 ));
1661 }
1662 }
1663 MacroDirectiveKind::Derive {
1664 ast_id,
1665 derive_attr,
1666 derive_pos,
1667 derive_macro_id,
1668 ..
1669 } => {
1670 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1671 directive.module_id,
1672 MacroCallKind::Derive {
1673 ast_id: ast_id.ast_id,
1674 derive_attr_index: *derive_attr,
1675 derive_index: *derive_pos as u32,
1676 derive_macro_id: *derive_macro_id,
1677 },
1678 ast_id.path.as_ref().clone(),
1679 ));
1680 }
1681 MacroDirectiveKind::Attr { .. } => {}
1683 }
1684 }
1685
1686 for import in &self.unresolved_imports {
1688 let &ImportDirective {
1689 module_id,
1690 import:
1691 Import {
1692 ref path,
1693 source: ImportSource { use_tree, id, is_prelude: _, kind: _ },
1694 ..
1695 },
1696 ..
1697 } = import;
1698 if matches!(
1699 (path.segments().first(), &path.kind),
1700 (Some(krate), PathKind::Plain | PathKind::Abs) if self.unresolved_extern_crates.contains(krate)
1701 ) {
1702 continue;
1703 }
1704 let item_tree_id = id.lookup(self.db).id;
1705 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1706 module_id,
1707 item_tree_id,
1708 use_tree,
1709 ));
1710 }
1711
1712 (self.def_map, self.local_def_map)
1713 }
1714}
1715
1716struct ModCollector<'a, 'db> {
1718 def_collector: &'a mut DefCollector<'db>,
1719 macro_depth: usize,
1720 module_id: ModuleId,
1721 tree_id: TreeId,
1722 item_tree: &'db ItemTree,
1723 mod_dir: ModDir,
1724}
1725
1726impl ModCollector<'_, '_> {
1727 fn collect_in_top_module(&mut self, items: &[ModItemId]) {
1728 self.collect(items, self.module_id.into())
1729 }
1730
1731 fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) {
1732 let krate = self.def_collector.def_map.krate;
1733 let is_crate_root = self.module_id == self.def_collector.def_map.root
1734 && self.def_collector.def_map.block.is_none();
1735
1736 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1739
1740 if let Some((prelude_module, _use)) = self.def_collector.def_map.prelude {
1742 if is_crate_root && prelude_module.krate(self.def_collector.db) != krate {
1744 cov_mark::hit!(prelude_is_macro_use);
1745 self.def_collector.import_macros_from_extern_crate(
1746 prelude_module.krate(self.def_collector.db),
1747 None,
1748 None,
1749 );
1750 }
1751 }
1752 let db = self.def_collector.db;
1753 let module_id = self.module_id;
1754 let update_def =
1755 |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
1756 def_collector.def_map.modules[module_id].scope.declare(id);
1757 def_collector.update(
1758 module_id,
1759 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))],
1760 vis,
1761 None,
1762 )
1763 };
1764 let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| {
1765 def_map
1766 .resolve_visibility(local_def_map, db, module_id, visibility, false)
1767 .unwrap_or(Visibility::Public)
1768 };
1769
1770 let mut process_mod_item = |item: ModItemId| {
1771 let attrs = match self.item_tree.attrs(item.ast_id()) {
1772 Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
1773 None => Attrs::EMPTY,
1774 Some(AttrsOrCfg::CfgDisabled(cfg)) => {
1775 let ast_id = item.ast_id().erase();
1776 self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg.0);
1777 return;
1778 }
1779 };
1780
1781 if let Err(()) = self.resolve_attributes(attrs, item, container) {
1782 return;
1785 }
1786
1787 let def_map = &mut self.def_collector.def_map;
1788 let local_def_map =
1789 self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map);
1790
1791 match item {
1792 ModItemId::Mod(m) => self.collect_module(m, attrs),
1793 ModItemId::Use(item_tree_id) => {
1794 let id = UseLoc {
1795 container: module_id,
1796 id: InFile::new(self.file_id(), item_tree_id),
1797 }
1798 .intern(db);
1799 let is_prelude = attrs.by_key(sym::prelude_import).exists();
1800 Import::from_use(self.item_tree, item_tree_id, id, is_prelude, |import| {
1801 self.def_collector.unresolved_imports.push(ImportDirective {
1802 module_id: self.module_id,
1803 import,
1804 status: PartialResolvedImport::Unresolved,
1805 });
1806 })
1807 }
1808 ModItemId::ExternCrate(item_tree_id) => {
1809 let item_tree::ExternCrate { name, visibility, alias } =
1810 &self.item_tree[item_tree_id];
1811
1812 let id = ExternCrateLoc {
1813 container: module_id,
1814 id: InFile::new(self.tree_id.file_id(), item_tree_id),
1815 }
1816 .intern(db);
1817 def_map.modules[self.module_id].scope.define_extern_crate_decl(id);
1818
1819 let is_self = *name == sym::self_;
1820 let resolved = if is_self {
1821 cov_mark::hit!(extern_crate_self_as);
1822 Some(def_map.crate_root(db))
1823 } else {
1824 self.def_collector
1825 .deps
1826 .get(name)
1827 .map(|dep| crate_def_map(db, dep.crate_id).root_module_id())
1828 };
1829
1830 let name = match alias {
1831 Some(ImportAlias::Alias(name)) => Some(name),
1832 Some(ImportAlias::Underscore) => None,
1833 None => Some(name),
1834 };
1835
1836 if let Some(resolved) = resolved {
1837 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]);
1838
1839 if is_crate_root {
1840 if let Some(name) = name {
1842 self.def_collector
1843 .local_def_map
1844 .extern_prelude
1845 .insert(name.clone(), (resolved, Some(id)));
1846 }
1847 if !is_self {
1849 self.process_macro_use_extern_crate(
1850 id,
1851 attrs.by_key(sym::macro_use).attrs(),
1852 resolved.krate(self.def_collector.db),
1853 );
1854 }
1855 }
1856
1857 self.def_collector.update(
1858 module_id,
1859 &[(
1860 name.cloned(),
1861 PerNs::types(
1862 resolved.into(),
1863 vis,
1864 Some(ImportOrExternCrate::ExternCrate(id)),
1865 ),
1866 )],
1867 vis,
1868 Some(ImportOrExternCrate::ExternCrate(id)),
1869 );
1870 } else {
1871 if let Some(name) = name {
1872 self.def_collector.unresolved_extern_crates.insert(name.clone());
1873 }
1874 self.def_collector.def_map.diagnostics.push(
1875 DefDiagnostic::unresolved_extern_crate(
1876 module_id,
1877 InFile::new(self.file_id(), item_tree_id),
1878 ),
1879 );
1880 }
1881 }
1882 ModItemId::ExternBlock(block) => {
1883 let extern_block_id = ExternBlockLoc {
1884 container: module_id,
1885 id: InFile::new(self.file_id(), block),
1886 }
1887 .intern(db);
1888 self.def_collector.def_map.modules[self.module_id]
1889 .scope
1890 .define_extern_block(extern_block_id);
1891 self.collect(
1892 &self.item_tree[block].children,
1893 ItemContainerId::ExternBlockId(extern_block_id),
1894 )
1895 }
1896 ModItemId::MacroCall(mac) => self.collect_macro_call(mac, container),
1897 ModItemId::MacroRules(id) => self.collect_macro_rules(id, module_id),
1898 ModItemId::Macro2(id) => self.collect_macro_def(id, module_id),
1899 ModItemId::Impl(imp) => {
1900 let impl_id =
1901 ImplLoc { container: module_id, id: InFile::new(self.file_id(), imp) }
1902 .intern(db);
1903 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1904 }
1905 ModItemId::Function(id) => {
1906 let it = &self.item_tree[id];
1907 let fn_id =
1908 FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), id) }
1909 .intern(db);
1910
1911 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1912
1913 if self.def_collector.def_map.block.is_none()
1914 && self.def_collector.is_proc_macro
1915 && self.module_id == self.def_collector.def_map.root
1916 && let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name)
1917 {
1918 self.def_collector.export_proc_macro(
1919 proc_macro,
1920 InFile::new(self.file_id(), id),
1921 fn_id,
1922 );
1923 }
1924
1925 update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
1926 }
1927 ModItemId::Struct(id) => {
1928 let it = &self.item_tree[id];
1929
1930 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1931 update_def(
1932 self.def_collector,
1933 StructLoc { container: module_id, id: InFile::new(self.file_id(), id) }
1934 .intern(db)
1935 .into(),
1936 &it.name,
1937 vis,
1938 !matches!(it.shape, FieldsShape::Record),
1939 );
1940 }
1941 ModItemId::Union(id) => {
1942 let it = &self.item_tree[id];
1943
1944 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1945 update_def(
1946 self.def_collector,
1947 UnionLoc { container: module_id, id: InFile::new(self.file_id(), id) }
1948 .intern(db)
1949 .into(),
1950 &it.name,
1951 vis,
1952 false,
1953 );
1954 }
1955 ModItemId::Enum(id) => {
1956 let it = &self.item_tree[id];
1957 let enum_ = EnumLoc {
1958 container: module_id,
1959 id: InFile::new(self.tree_id.file_id(), id),
1960 }
1961 .intern(db);
1962
1963 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1964 update_def(self.def_collector, enum_.into(), &it.name, vis, false);
1965 }
1966 ModItemId::Const(id) => {
1967 let it = &self.item_tree[id];
1968 let const_id =
1969 ConstLoc { container, id: InFile::new(self.tree_id.file_id(), id) }
1970 .intern(db);
1971
1972 match &it.name {
1973 Some(name) => {
1974 let vis =
1975 resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1976 update_def(self.def_collector, const_id.into(), name, vis, false);
1977 }
1978 None => {
1979 self.def_collector.def_map.modules[self.module_id]
1981 .scope
1982 .define_unnamed_const(const_id);
1983 }
1984 }
1985 }
1986 ModItemId::Static(id) => {
1987 let it = &self.item_tree[id];
1988
1989 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
1990 update_def(
1991 self.def_collector,
1992 StaticLoc { container, id: InFile::new(self.file_id(), id) }
1993 .intern(db)
1994 .into(),
1995 &it.name,
1996 vis,
1997 false,
1998 );
1999 }
2000 ModItemId::Trait(id) => {
2001 let it = &self.item_tree[id];
2002
2003 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2004 update_def(
2005 self.def_collector,
2006 TraitLoc { container: module_id, id: InFile::new(self.file_id(), id) }
2007 .intern(db)
2008 .into(),
2009 &it.name,
2010 vis,
2011 false,
2012 );
2013 }
2014 ModItemId::TypeAlias(id) => {
2015 let it = &self.item_tree[id];
2016
2017 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2018 update_def(
2019 self.def_collector,
2020 TypeAliasLoc { container, id: InFile::new(self.file_id(), id) }
2021 .intern(db)
2022 .into(),
2023 &it.name,
2024 vis,
2025 false,
2026 );
2027 }
2028 }
2029 };
2030
2031 if is_crate_root {
2035 items
2036 .iter()
2037 .filter(|it| matches!(it, ModItemId::ExternCrate(..)))
2038 .copied()
2039 .for_each(&mut process_mod_item);
2040 items
2041 .iter()
2042 .filter(|it| !matches!(it, ModItemId::ExternCrate(..)))
2043 .copied()
2044 .for_each(process_mod_item);
2045 } else {
2046 items.iter().copied().for_each(process_mod_item);
2047 }
2048 }
2049
2050 fn process_macro_use_extern_crate<'a>(
2051 &mut self,
2052 extern_crate_id: ExternCrateId,
2053 macro_use_attrs: impl Iterator<Item = &'a Attr>,
2054 target_crate: Crate,
2055 ) {
2056 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
2057 let mut single_imports = Vec::new();
2058 for attr in macro_use_attrs {
2059 let Some(paths) = attr.parse_path_comma_token_tree(self.def_collector.db) else {
2060 self.def_collector.import_macros_from_extern_crate(
2063 target_crate,
2064 None,
2065 Some(extern_crate_id),
2066 );
2067 return;
2068 };
2069 for (path, _, _) in paths {
2070 if let Some(name) = path.as_ident() {
2071 single_imports.push(name.clone());
2072 }
2073 }
2074 }
2075
2076 self.def_collector.import_macros_from_extern_crate(
2077 target_crate,
2078 Some(single_imports),
2079 Some(extern_crate_id),
2080 );
2081 }
2082
2083 fn collect_module(&mut self, module_ast_id: ItemTreeAstId<Mod>, attrs: Attrs<'_>) {
2084 let path_attr = attrs.by_key(sym::path).string_value_unescape();
2085 let is_macro_use = attrs.by_key(sym::macro_use).exists();
2086 let module = &self.item_tree[module_ast_id];
2087 match &module.kind {
2088 ModKind::Inline { items } => {
2090 let module_id = self.push_child_module(
2091 module.name.clone(),
2092 module_ast_id,
2093 None,
2094 &self.item_tree[module.visibility],
2095 );
2096
2097 let Some(mod_dir) =
2098 self.mod_dir.descend_into_definition(&module.name, path_attr.as_deref())
2099 else {
2100 return;
2101 };
2102 ModCollector {
2103 def_collector: &mut *self.def_collector,
2104 macro_depth: self.macro_depth,
2105 module_id,
2106 tree_id: self.tree_id,
2107 item_tree: self.item_tree,
2108 mod_dir,
2109 }
2110 .collect_in_top_module(items);
2111 if is_macro_use {
2112 self.import_all_legacy_macros(module_id);
2113 }
2114 }
2115 ModKind::Outline => {
2117 let ast_id = AstId::new(self.file_id(), module_ast_id);
2118 let db = self.def_collector.db;
2119 match self.mod_dir.resolve_declaration(
2120 db,
2121 self.file_id(),
2122 &module.name,
2123 path_attr.as_deref(),
2124 self.def_collector.def_map.krate,
2125 ) {
2126 Ok((file_id, is_mod_rs, mod_dir)) => {
2127 let item_tree = db.file_item_tree(file_id.into());
2128 match item_tree.top_level_attrs() {
2129 AttrsOrCfg::CfgDisabled(cfg) => {
2130 self.emit_unconfigured_diagnostic(
2131 InFile::new(self.file_id(), module_ast_id.erase()),
2132 &cfg.0,
2133 );
2134 }
2135 AttrsOrCfg::Enabled { attrs } => {
2136 let module_id = self.push_child_module(
2137 module.name.clone(),
2138 ast_id.value,
2139 Some((file_id, is_mod_rs)),
2140 &self.item_tree[module.visibility],
2141 );
2142 ModCollector {
2143 def_collector: self.def_collector,
2144 macro_depth: self.macro_depth,
2145 module_id,
2146 tree_id: TreeId::new(file_id.into(), None),
2147 item_tree,
2148 mod_dir,
2149 }
2150 .collect_in_top_module(item_tree.top_level_items());
2151 let is_macro_use =
2152 is_macro_use || attrs.as_ref().by_key(sym::macro_use).exists();
2153 if is_macro_use {
2154 self.import_all_legacy_macros(module_id);
2155 }
2156 }
2157 }
2158 }
2159 Err(candidates) => {
2160 self.push_child_module(
2161 module.name.clone(),
2162 ast_id.value,
2163 None,
2164 &self.item_tree[module.visibility],
2165 );
2166 self.def_collector.def_map.diagnostics.push(
2167 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
2168 );
2169 }
2170 };
2171 }
2172 }
2173 }
2174
2175 fn push_child_module(
2176 &mut self,
2177 name: Name,
2178 declaration: FileAstId<ast::Module>,
2179 definition: Option<(EditionedFileId, bool)>,
2180 visibility: &crate::visibility::RawVisibility,
2181 ) -> ModuleId {
2182 let vis = self
2183 .def_collector
2184 .def_map
2185 .resolve_visibility(
2186 self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map),
2187 self.def_collector.db,
2188 self.module_id,
2189 visibility,
2190 false,
2191 )
2192 .unwrap_or(Visibility::Public);
2193 let origin = match definition {
2194 None => {
2195 ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id }
2196 }
2197 Some((definition, is_mod_rs)) => ModuleOrigin::File {
2198 declaration,
2199 definition,
2200 is_mod_rs,
2201 declaration_tree_id: self.tree_id,
2202 },
2203 };
2204
2205 let module = unsafe {
2206 crate::ModuleIdLt::new(
2207 self.def_collector.db,
2208 self.def_collector.def_map.krate,
2209 self.def_collector.def_map.block_id(),
2210 )
2211 .to_static()
2212 };
2213 let def_map = &mut self.def_collector.def_map;
2214 let modules = &mut def_map.modules;
2215 let mut data = ModuleData::new(origin, vis, Some(self.module_id));
2216 for (name, macs) in modules[self.module_id].scope.legacy_macros() {
2217 for &mac in macs {
2218 data.scope.define_legacy_macro(name.clone(), mac);
2219 }
2220 }
2221 modules[self.module_id].children.insert(name.clone(), module);
2222 modules.insert(module, data);
2223
2224 let def = ModuleDefId::from(module);
2225
2226 def_map.modules[self.module_id].scope.declare(def);
2227 self.def_collector.update(
2228 self.module_id,
2229 &[(Some(name), PerNs::from_def(def, vis, false, None))],
2230 vis,
2231 None,
2232 );
2233 module
2234 }
2235
2236 fn resolve_attributes(
2244 &mut self,
2245 attrs: Attrs<'_>,
2246 mod_item: ModItemId,
2247 container: ItemContainerId,
2248 ) -> Result<(), ()> {
2249 let ignore_up_to = self
2250 .def_collector
2251 .skip_attrs
2252 .get(&InFile::new(self.file_id(), mod_item.ast_id()))
2253 .copied();
2254 for (attr_id, attr) in attrs.iter_after(ignore_up_to) {
2255 if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
2256 continue;
2257 }
2258 tracing::debug!(
2259 "non-builtin attribute {}",
2260 attr.path.display(self.def_collector.db, Edition::LATEST)
2261 );
2262
2263 let ast_id = AstIdWithPath::new(self.file_id(), mod_item.ast_id(), attr.path.clone());
2264 self.def_collector.unresolved_macros.push(MacroDirective {
2265 module_id: self.module_id,
2266 depth: self.macro_depth + 1,
2267 kind: MacroDirectiveKind::Attr {
2268 ast_id,
2269 attr_id,
2270 attr: attr.clone(),
2271 mod_item,
2272 tree: self.tree_id,
2273 item_tree: self.item_tree,
2274 },
2275 container,
2276 });
2277
2278 return Err(());
2279 }
2280
2281 Ok(())
2282 }
2283
2284 fn collect_macro_rules(&mut self, ast_id: ItemTreeAstId<MacroRules>, module: ModuleId) {
2285 let krate = self.def_collector.def_map.krate;
2286 let mac = &self.item_tree[ast_id];
2287 let attrs = match self.item_tree.attrs(ast_id.upcast()) {
2288 Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
2289 None => Attrs::EMPTY,
2290 Some(AttrsOrCfg::CfgDisabled(_)) => {
2291 unreachable!("we only get here if the macro is not cfg'ed out")
2292 }
2293 };
2294 let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2295
2296 let export_attr = || attrs.by_key(sym::macro_export);
2297
2298 let is_export = export_attr().exists();
2299 let local_inner = if is_export {
2300 export_attr().tt_values().flat_map(|it| it.iter()).any(|it| match it {
2301 tt::TtElement::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros,
2302 _ => false,
2303 })
2304 } else {
2305 false
2306 };
2307
2308 let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2310 let name;
2312 let name = match attrs.by_key(sym::rustc_builtin_macro).string_value_with_span() {
2313 Some((it, span)) => {
2314 name = Name::new_symbol(it.clone(), span.ctx);
2315 &name
2316 }
2317 None => {
2318 let explicit_name =
2319 attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
2320 match tt.token_trees().flat_tokens().first() {
2321 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
2322 _ => None,
2323 }
2324 });
2325 match explicit_name {
2326 Some(ident) => {
2327 name = ident.as_name();
2328 &name
2329 }
2330 None => &mac.name,
2331 }
2332 }
2333 };
2334 match find_builtin_macro(name) {
2335 Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
2336 Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
2337 None => {
2338 self.def_collector
2339 .def_map
2340 .diagnostics
2341 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2342 return;
2343 }
2344 }
2345 } else {
2346 let id = InFile::new(self.file_id(), ast_id);
2348 let decl_expander = self.def_collector.db.decl_macro_expander(krate, id.upcast());
2349 let styles = decl_expander.mac.rule_styles();
2350 MacroExpander::Declarative { styles }
2351 };
2352 let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2353
2354 let mut flags = MacroRulesLocFlags::empty();
2355 flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
2356 flags.set(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE, allow_internal_unsafe);
2357
2358 let macro_id = MacroRulesLoc {
2359 container: module,
2360 id: InFile::new(self.file_id(), ast_id),
2361 flags,
2362 expander,
2363 edition: self.def_collector.def_map.data.edition,
2364 }
2365 .intern(self.def_collector.db);
2366 self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2367 self.def_collector.define_macro_rules(
2368 self.module_id,
2369 mac.name.clone(),
2370 macro_id,
2371 is_export,
2372 );
2373 }
2374
2375 fn collect_macro_def(&mut self, ast_id: ItemTreeAstId<Macro2>, module: ModuleId) {
2376 let krate = self.def_collector.def_map.krate;
2377 let mac = &self.item_tree[ast_id];
2378 let attrs = match self.item_tree.attrs(ast_id.upcast()) {
2379 Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
2380 None => Attrs::EMPTY,
2381 Some(AttrsOrCfg::CfgDisabled(_)) => {
2382 unreachable!("we only get here if the macro is not cfg'ed out")
2383 }
2384 };
2385 let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2386
2387 let mut helpers_opt = None;
2389 let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2390 if let Some(expander) = find_builtin_macro(&mac.name) {
2391 match expander {
2392 Either::Left(it) => MacroExpander::BuiltIn(it),
2393 Either::Right(it) => MacroExpander::BuiltInEager(it),
2394 }
2395 } else if let Some(expander) = find_builtin_derive(&mac.name) {
2396 if let Some(attr) = attrs.by_key(sym::rustc_builtin_macro).tt_values().next() {
2397 if let Some((name, helpers)) = parse_macro_name_and_helper_attrs(attr) {
2401 stdx::always!(
2405 name == mac.name,
2406 "built-in macro {} has #[rustc_builtin_macro] which declares different name {}",
2407 mac.name.display(self.def_collector.db, Edition::LATEST),
2408 name.display(self.def_collector.db, Edition::LATEST),
2409 );
2410 helpers_opt = Some(helpers);
2411 }
2412 }
2413 MacroExpander::BuiltInDerive(expander)
2414 } else if let Some(expander) = find_builtin_attr(&mac.name) {
2415 MacroExpander::BuiltInAttr(expander)
2416 } else {
2417 self.def_collector
2418 .def_map
2419 .diagnostics
2420 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2421 return;
2422 }
2423 } else {
2424 let id = InFile::new(self.file_id(), ast_id);
2426 let decl_expander = self.def_collector.db.decl_macro_expander(krate, id.upcast());
2427 let styles = decl_expander.mac.rule_styles();
2428 MacroExpander::Declarative { styles }
2429 };
2430 let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2431
2432 let macro_id = Macro2Loc {
2433 container: module,
2434 id: InFile::new(self.file_id(), ast_id),
2435 expander,
2436 allow_internal_unsafe,
2437 edition: self.def_collector.def_map.data.edition,
2438 }
2439 .intern(self.def_collector.db);
2440 self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2441 self.def_collector.define_macro_def(
2442 self.module_id,
2443 mac.name.clone(),
2444 macro_id,
2445 &self.item_tree[mac.visibility],
2446 );
2447 if let Some(helpers) = helpers_opt
2448 && self.def_collector.def_map.block.is_none()
2449 {
2450 Arc::get_mut(&mut self.def_collector.def_map.data)
2451 .unwrap()
2452 .exported_derives
2453 .insert(macro_id.into(), helpers);
2454 }
2455 }
2456
2457 fn collect_macro_call(
2458 &mut self,
2459 ast_id: FileAstId<ast::MacroCall>,
2460 container: ItemContainerId,
2461 ) {
2462 let &MacroCall { ref path, expand_to, ctxt } = &self.item_tree[ast_id];
2463 let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone());
2464 let db = self.def_collector.db;
2465
2466 let mut eager_callback_buffer = vec![];
2471 if let Ok(res) = macro_call_as_call_id(
2473 db,
2474 ast_id.ast_id,
2475 &ast_id.path,
2476 ctxt,
2477 expand_to,
2478 self.def_collector.def_map.krate,
2479 |path| {
2480 path.as_ident().and_then(|name| {
2481 let def_map = &self.def_collector.def_map;
2482 def_map
2483 .with_ancestor_maps(db, self.module_id, &mut |map, module| {
2484 map[module].scope.get_legacy_macro(name)?.last().copied()
2485 })
2486 .or_else(|| def_map[self.module_id].scope.get(name).take_macros())
2487 .or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0))
2488 .filter(|&id| sub_namespace_match(db, id, Some(MacroSubNs::Bang)))
2489 .map(|it| self.def_collector.db.macro_def(it))
2490 })
2491 },
2492 &mut |ptr, call_id| eager_callback_buffer.push((ptr, call_id)),
2493 ) {
2494 for (ptr, call_id) in eager_callback_buffer {
2495 self.def_collector.def_map.modules[self.module_id]
2496 .scope
2497 .add_macro_invoc(ptr.map(|(_, it)| it), call_id);
2498 }
2499 if res.err.is_none() {
2502 if let Some(call_id) = res.value {
2505 self.def_collector.def_map.modules[self.module_id]
2506 .scope
2507 .add_macro_invoc(ast_id.ast_id, call_id);
2508 self.def_collector.collect_macro_expansion(
2509 self.module_id,
2510 call_id,
2511 self.macro_depth + 1,
2512 container,
2513 None,
2514 );
2515 }
2516
2517 return;
2518 }
2519 }
2520
2521 self.def_collector.unresolved_macros.push(MacroDirective {
2523 module_id: self.module_id,
2524 depth: self.macro_depth + 1,
2525 kind: MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt },
2526 container,
2527 });
2528 }
2529
2530 fn import_all_legacy_macros(&mut self, module_id: ModuleId) {
2531 let [Some(source), Some(target)] =
2532 self.def_collector.def_map.modules.get_disjoint_mut([&module_id, &self.module_id])
2533 else {
2534 return;
2535 };
2536
2537 for (name, macs) in source.scope.legacy_macros() {
2538 if let Some(&mac) = macs.last() {
2539 target.scope.define_legacy_macro(name.clone(), mac);
2540 }
2541 }
2542 }
2543
2544 fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedAstId, cfg: &CfgExpr) {
2545 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2546 self.module_id,
2547 ast_id,
2548 cfg.clone(),
2549 self.def_collector.cfg_options.clone(),
2550 ));
2551 }
2552
2553 #[inline]
2554 fn file_id(&self) -> HirFileId {
2555 self.tree_id.file_id()
2556 }
2557}
2558
2559#[cfg(test)]
2560mod tests {
2561 use test_fixture::WithFixture;
2562
2563 use crate::test_db::TestDB;
2564
2565 use super::*;
2566
2567 fn do_resolve(not_ra_fixture: &str) {
2568 let (db, _) = TestDB::with_single_file(not_ra_fixture);
2569 let krate = db.test_crate();
2570
2571 crate_def_map(&db, krate);
2572 }
2573
2574 #[test]
2575 fn test_macro_expand_will_stop_1() {
2576 do_resolve(
2577 r#"
2578macro_rules! foo {
2579 ($($ty:ty)*) => { foo!($($ty)*); }
2580}
2581foo!(KABOOM);
2582"#,
2583 );
2584 do_resolve(
2585 r#"
2586macro_rules! foo {
2587 ($($ty:ty)*) => { foo!(() $($ty)*); }
2588}
2589foo!(KABOOM);
2590"#,
2591 );
2592 }
2593
2594 #[ignore]
2595 #[test]
2596 fn test_macro_expand_will_stop_2() {
2597 do_resolve(
2603 r#"
2604macro_rules! foo {
2605 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2606}
2607foo!(KABOOM);
2608"#,
2609 );
2610 }
2611}