1use std::{iter, mem, ops::Range};
7
8use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin, SourceDatabase};
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::{BuiltinDeriveExpander, find_builtin_attr, find_builtin_derive, find_builtin_macro},
16 mod_path::{ModPath, PathKind},
17 name::{AsName, Name},
18 proc_macro::{CustomProcMacroExpander, ProcMacros},
19};
20use intern::{Interned, Symbol, sym};
21use itertools::izip;
22use la_arena::Idx;
23use rustc_hash::{FxHashMap, FxHashSet};
24use smallvec::SmallVec;
25use span::{Edition, FileAstId, ROOT_ERASED_FILE_AST_ID, SyntaxContext};
26use stdx::always;
27use syntax::ast;
28use triomphe::Arc;
29
30use crate::{
31 AdtId, AssocItemId, AstId, AstIdWithPath, BuiltinDeriveImplId, BuiltinDeriveImplLoc, ConstLoc,
32 EnumLoc, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, FxIndexMap,
33 ImplLoc, Intern, ItemContainerId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
34 MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
35 ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId,
36 UseLoc, file_item_tree,
37 item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
38 item_tree::{
39 self, Attrs, AttrsOrCfg, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2,
40 MacroCall, MacroRules, Mod, ModItemId, ModItemKind, ModKind, StructValueNsCtor, TreeId,
41 Use,
42 },
43 macro_call_as_call_id,
44 nameres::{
45 BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
46 assoc::TraitItems,
47 attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
48 crate_def_map,
49 diagnostics::DefDiagnostic,
50 mod_resolution::ModDir,
51 path_resolution::{ReachedFixedPoint, ResolvePathResult},
52 proc_macro::{ProcMacroDef, ProcMacroKind, parse_macro_name_and_helper_attrs},
53 sub_namespace_match,
54 },
55 per_ns::{Item, PerNs},
56 tt,
57 visibility::{RawVisibility, Visibility},
58};
59
60const GLOB_RECURSION_LIMIT: usize = 100;
61const FIXED_POINT_LIMIT: usize = 8192;
62
63pub(super) fn collect_defs(
64 db: &dyn SourceDatabase,
65 def_map: DefMap,
66 tree_id: TreeId,
67 crate_local_def_map: Option<&LocalDefMap>,
68) -> (DefMap, LocalDefMap) {
69 let krate = &def_map.krate.data(db);
70 let cfg_options = def_map.krate.cfg_options(db);
71
72 let mut deps =
74 FxIndexMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
75 for dep in &krate.dependencies {
76 tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
77
78 deps.insert(dep.as_name(), dep.clone());
79 }
80
81 let proc_macros = if krate.target_kind.is_proc_macro() {
82 ProcMacros::get_for_crate(db, def_map.krate)
83 .and_then(|proc_macros| {
84 proc_macros.list(tree_id.file_id().syntax_context(db, krate.edition))
85 })
86 .unwrap_or_default()
87 } else {
88 Default::default()
89 };
90
91 let mut collector = DefCollector {
92 db,
93 def_map,
94 local_def_map: LocalDefMap::default(),
95 crate_local_def_map,
96 deps,
97 glob_imports: FxHashMap::default(),
98 unresolved_imports: Vec::new(),
99 indeterminate_imports: Vec::new(),
100 unresolved_macros: Vec::new(),
101 mod_dirs: FxHashMap::default(),
102 cfg_options,
103 proc_macros,
104 from_glob_import: Default::default(),
105 skip_attrs: Default::default(),
106 prev_active_attrs: Default::default(),
107 unresolved_extern_crates: Default::default(),
108 is_proc_macro: krate.target_kind.is_proc_macro(),
109 deferred_builtin_derives: Default::default(),
110 };
111 if tree_id.is_block() {
112 collector.seed_with_inner(tree_id);
113 } else {
114 collector.seed_with_top_level();
115 }
116 collector.collect();
117 let (mut def_map, mut local_def_map) = collector.finish();
118 def_map.shrink_to_fit();
119 local_def_map.shrink_to_fit();
120 (def_map, local_def_map)
121}
122
123#[derive(Copy, Clone, Debug, Eq, PartialEq)]
124enum PartialResolvedImport {
125 Unresolved,
127 Indeterminate(PerNs),
129 Resolved(PerNs),
131}
132
133impl PartialResolvedImport {
134 fn namespaces(self) -> PerNs {
135 match self {
136 PartialResolvedImport::Unresolved => PerNs::none(),
137 PartialResolvedImport::Indeterminate(ns) | PartialResolvedImport::Resolved(ns) => ns,
138 }
139 }
140}
141
142#[derive(Clone, Debug, Eq, PartialEq)]
143struct ImportSource {
144 use_tree: Idx<ast::UseTree>,
145 id: UseId,
146 is_prelude: bool,
147 kind: ImportKind,
148}
149
150#[derive(Debug, Eq, PartialEq)]
151struct Import {
152 path: ModPath,
153 alias: Option<ImportAlias>,
154 visibility: RawVisibility,
155 source: ImportSource,
156}
157
158impl Import {
159 fn from_use(
160 tree: &ItemTree,
161 item: &Use,
162 id: UseId,
163 is_prelude: bool,
164 mut cb: impl FnMut(Self),
165 ) {
166 let visibility = &tree[item.visibility];
167 item.expand(|idx, path, kind, alias| {
168 cb(Self {
169 path,
170 alias,
171 visibility: visibility.clone(),
172 source: ImportSource { use_tree: idx, id, is_prelude, kind },
173 });
174 });
175 }
176}
177
178#[derive(Debug, Eq, PartialEq)]
179struct ImportDirective {
180 module_id: ModuleId,
182 import: Import,
183 status: PartialResolvedImport,
184}
185
186#[derive(Clone, Debug, Eq, PartialEq)]
187struct MacroDirective<'db> {
188 module_id: ModuleId,
189 depth: u32,
190 kind: MacroDirectiveKind<'db>,
191 container: ItemContainerId,
192}
193
194#[derive(Clone, Debug, Eq, PartialEq)]
195enum MacroDirectiveKind<'db> {
196 FnLike {
197 ast_id: AstIdWithPath<ast::MacroCall>,
198 expand_to: ExpandTo,
199 ctxt: SyntaxContext,
200 },
201 Derive {
202 ast_id: AstIdWithPath<ast::Adt>,
203 derive_attr: AttrId,
204 derive_pos: usize,
205 ctxt: SyntaxContext,
206 derive_macro_id: MacroCallId,
208 },
209 Attr {
210 ast_id: AstIdWithPath<ast::Item>,
211 attr_id: AttrId,
212 attr: Attr,
213 mod_item: ModItemId,
214 tree: TreeId,
215 item_tree: &'db ItemTree,
216 },
217}
218
219#[derive(Debug)]
220struct DeferredBuiltinDerive {
221 call_id: MacroCallId,
222 derive: BuiltinDeriveExpander,
223 module_id: ModuleId,
224 depth: u32,
225 container: ItemContainerId,
226 derive_attr_id: AttrId,
227 derive_index: u32,
228 helpers_range: Range<usize>,
229}
230
231struct DefCollector<'db> {
233 db: &'db dyn SourceDatabase,
234 def_map: DefMap,
235 local_def_map: LocalDefMap,
236 crate_local_def_map: Option<&'db LocalDefMap>,
238 deps: FxIndexMap<Name, BuiltDependency>,
240 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, Visibility, GlobId)>>,
241 unresolved_imports: Vec<ImportDirective>,
242 indeterminate_imports: Vec<(ImportDirective, PerNs)>,
243 unresolved_macros: Vec<MacroDirective<'db>>,
244 unresolved_extern_crates: FxHashSet<Name>,
248 mod_dirs: FxHashMap<ModuleId, ModDir>,
249 cfg_options: &'db CfgOptions,
250 proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>,
255 is_proc_macro: bool,
256 from_glob_import: PerNsGlobImports,
257 skip_attrs: FxHashMap<InFile<ModItemId>, AttrId>,
265 prev_active_attrs: FxHashMap<AstId<ast::Item>, SmallVec<[AttrId; 1]>>,
269 deferred_builtin_derives: FxHashMap<AstId<ast::Item>, Vec<DeferredBuiltinDerive>>,
274}
275
276impl<'db> DefCollector<'db> {
277 fn seed_with_top_level(&mut self) {
278 let _p = tracing::info_span!("seed_with_top_level").entered();
279
280 let file_id = self.def_map.krate.root_file_id(self.db);
281 let item_tree = file_item_tree(self.db, file_id.into(), self.def_map.krate);
282 let attrs = match item_tree.top_level_attrs() {
283 Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
284 None => Attrs::EMPTY,
285 Some(AttrsOrCfg::CfgDisabled(it)) => it.1.as_ref(),
286 };
287 let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
288
289 for attr in &*attrs {
291 let Some(attr_name) = attr.path.as_ident() else { continue };
292
293 match () {
294 () if *attr_name == sym::recursion_limit => {
295 if let Some(limit) = attr.string_value()
296 && let Ok(limit) = limit.parse()
297 {
298 crate_data.recursion_limit = Some(limit);
299 }
300 }
301 () if *attr_name == sym::crate_type => {
302 if attr.string_value() == Some("proc-macro") {
303 self.is_proc_macro = true;
304 }
305 }
306 () if *attr_name == sym::no_core => crate_data.no_core = true,
307 () if *attr_name == sym::no_std => crate_data.no_std = true,
308 () if *attr_name == sym::rustc_coherence_is_core => {
309 crate_data.rustc_coherence_is_core = true;
310 }
311 () if *attr_name == sym::feature => {
312 let features =
313 attr.parse_path_comma_token_tree(self.db).into_iter().flatten().filter_map(
314 |(feat, _, _)| match feat.segments() {
315 [name] => Some(name.symbol().clone()),
316 _ => None,
317 },
318 );
319 features.for_each(|feature| crate_data.unstable_features.enable(feature));
320 }
321 () if *attr_name == sym::register_tool => {
322 if let Some(ident) = attr.single_ident_value() {
323 crate_data.registered_tools.push(ident.sym.clone());
324 cov_mark::hit!(register_tool);
325 }
326 }
327 () => (),
328 }
329 }
330
331 for (name, dep) in &self.deps {
332 if dep.is_prelude() {
334 let skip = dep.is_sysroot()
348 && match dep.crate_id.data(self.db).origin {
349 CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
350 CrateOrigin::Lang(LangCrateOrigin::Std) => {
351 crate_data.no_core || crate_data.no_std
352 }
353 _ => false,
354 };
355 if skip {
356 continue;
357 }
358
359 self.local_def_map.extern_prelude.insert(
364 name.clone(),
365 (crate_def_map(self.db, dep.crate_id).root_module_id(), None),
366 );
367 }
368 }
369
370 self.inject_prelude();
371
372 if let Some(AttrsOrCfg::CfgDisabled(attrs)) = item_tree.top_level_attrs() {
373 let (cfg_expr, _) = &**attrs;
374 self.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
375 self.def_map.root,
376 InFile::new(file_id.into(), ROOT_ERASED_FILE_AST_ID),
377 cfg_expr.clone(),
378 self.cfg_options.clone(),
379 ));
380 return;
381 }
382
383 let module_id = self.def_map.root;
384 ModCollector {
385 def_collector: self,
386 macro_depth: 0,
387 module_id,
388 tree_id: TreeId::new(file_id.into(), None),
389 item_tree,
390 mod_dir: ModDir::root(),
391 }
392 .collect_in_top_module(item_tree.top_level_items());
393 Arc::get_mut(&mut self.def_map.data).unwrap().shrink_to_fit();
394 }
395
396 fn seed_with_inner(&mut self, tree_id: TreeId) {
397 let item_tree = tree_id.item_tree(self.db, self.def_map.krate);
398 let is_cfg_enabled =
399 matches!(item_tree.top_level_attrs(), Some(AttrsOrCfg::Enabled { .. }) | None);
400 if is_cfg_enabled {
401 self.inject_prelude();
402
403 let module_id = self.def_map.root;
404 let macro_depth = tree_id.file_id().macro_expansion_depth(self.db);
408 ModCollector {
409 def_collector: self,
410 macro_depth,
411 module_id,
412 tree_id,
413 item_tree,
414 mod_dir: ModDir::root(),
415 }
416 .collect_in_top_module(item_tree.top_level_items());
417 }
418 }
419
420 fn resolution_loop(&mut self) {
421 let _p = tracing::info_span!("DefCollector::resolution_loop").entered();
422
423 let mut i = 0;
425 'resolve_attr: loop {
426 let _p = tracing::info_span!("resolve_macros loop").entered();
427 'resolve_macros: loop {
428 self.db.unwind_if_revision_cancelled();
429
430 {
431 let _p = tracing::info_span!("resolve_imports loop").entered();
432
433 'resolve_imports: loop {
434 if self.resolve_imports() == ReachedFixedPoint::Yes {
435 break 'resolve_imports;
436 }
437 }
438 }
439 if self.resolve_macros() == ReachedFixedPoint::Yes {
440 break 'resolve_macros;
441 }
442
443 i += 1;
444 if i > FIXED_POINT_LIMIT {
445 tracing::error!("name resolution is stuck");
446 break 'resolve_attr;
447 }
448 }
449
450 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
451 break 'resolve_attr;
452 }
453 }
454 }
455
456 fn collect(&mut self) {
457 let _p = tracing::info_span!("DefCollector::collect").entered();
458
459 self.resolution_loop();
460
461 let unresolved_imports = mem::take(&mut self.unresolved_imports);
462 for directive in &unresolved_imports {
464 self.record_resolved_import(directive);
465 }
466 self.unresolved_imports = unresolved_imports;
467
468 if self.is_proc_macro {
469 let module_id = self.def_map.root_module_id();
475 let root = &mut self.def_map.modules[module_id];
476 root.scope.censor_non_proc_macros(self.def_map.krate);
477 }
478 }
479
480 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
490 cov_mark::hit!(unresolved_attribute_fallback);
491
492 let unresolved_attr =
493 self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
494 .kind
495 {
496 MacroDirectiveKind::Attr { ast_id, mod_item, attr_id, attr, tree, item_tree } => {
497 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
498 directive.module_id,
499 MacroCallKind::Attr {
500 ast_id: ast_id.ast_id,
501 attr_args: None,
502 censored_attr_ids: AttrMacroAttrIds::from_one(*attr_id),
503 },
504 (*attr.path).clone(),
505 ));
506
507 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr_id);
508
509 Some((idx, directive, *mod_item, *tree, *item_tree))
510 }
511 _ => None,
512 });
513
514 match unresolved_attr {
515 Some((
516 pos,
517 &MacroDirective { module_id, depth, container, .. },
518 mod_item,
519 tree_id,
520 item_tree,
521 )) => {
522 let mod_dir = self.mod_dirs[&module_id].clone();
524 ModCollector {
525 def_collector: self,
526 macro_depth: depth,
527 module_id,
528 tree_id,
529 item_tree,
530 mod_dir,
531 }
532 .collect(&[mod_item], container);
533
534 self.unresolved_macros.swap_remove(pos);
535 ReachedFixedPoint::No
537 }
538 None => ReachedFixedPoint::Yes,
539 }
540 }
541
542 fn inject_prelude(&mut self) {
543 if self.def_map.data.no_core {
546 return;
548 }
549
550 let krate = if self.def_map.data.no_std {
551 Name::new_symbol_root(sym::core)
552 } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std) {
553 Name::new_symbol_root(sym::std)
554 } else {
555 Name::new_symbol_root(sym::core)
558 };
559
560 let edition = match self.def_map.data.edition {
561 Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015),
562 Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018),
563 Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021),
564 Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024),
565 };
566
567 let path_kind = match self.def_map.data.edition {
568 Edition::Edition2015 => PathKind::Plain,
569 _ => PathKind::Abs,
570 };
571 let path = ModPath::from_segments(
572 path_kind,
573 [krate, Name::new_symbol_root(sym::prelude), edition],
574 );
575
576 let (per_ns, _) = self.def_map.resolve_path(
577 self.crate_local_def_map.unwrap_or(&self.local_def_map),
578 self.db,
579 self.def_map.root_module_id(),
580 &path,
581 BuiltinShadowMode::Other,
582 None,
583 );
584
585 match per_ns.types {
586 Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
587 self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
588 }
589 types => {
590 tracing::debug!(
591 "could not resolve prelude path `{}` to module (resolved to {:?})",
592 path.display(self.db, Edition::LATEST),
593 types
594 );
595 }
596 }
597 }
598
599 fn local_def_map(&mut self) -> &LocalDefMap {
600 self.crate_local_def_map.unwrap_or(&self.local_def_map)
601 }
602
603 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>, fn_id: FunctionId) {
620 let kind = def.kind.to_basedb_kind();
621 let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) {
622 Some(_)
623 if kind == hir_expand::proc_macro::ProcMacroKind::Attr
624 && !crate::ExpandProcAttrMacros::get(self.db).enabled(self.db) =>
625 {
626 (CustomProcMacroExpander::disabled_proc_attr(), kind)
627 }
628 Some(&(_, _, true)) => (CustomProcMacroExpander::disabled(), kind),
629 Some(&(_, expander, false)) => (expander, kind),
630 None => (CustomProcMacroExpander::missing_expander(), kind),
631 };
632
633 let proc_macro_id = ProcMacroLoc {
634 container: self.def_map.root_module_id(),
635 id: ast_id,
636 expander,
637 kind,
638 edition: self.def_map.data.edition,
639 }
640 .intern(self.db);
641
642 self.def_map.macro_def_to_macro_id.insert(ast_id.erase(), proc_macro_id.into());
643 self.define_proc_macro(def.name.clone(), proc_macro_id);
644 let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
645 if let ProcMacroKind::Derive { helpers } = def.kind {
646 crate_data.exported_derives.insert(proc_macro_id.into(), helpers);
647 }
648 crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
649 crate_data.fn_proc_macro_mapping_back.insert(proc_macro_id, fn_id);
650 }
651
652 fn define_macro_rules(
678 &mut self,
679 module_id: ModuleId,
680 name: Name,
681 macro_: MacroRulesId,
682 export: bool,
683 ) {
684 self.define_legacy_macro(module_id, name.clone(), macro_.into());
686
687 if export {
691 let module_id = self.def_map.root;
692 self.def_map.modules[module_id].scope.declare(macro_.into());
693 self.update(
694 module_id,
695 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
696 Visibility::Public,
697 None,
698 );
699 }
700 }
701
702 fn define_legacy_macro(&mut self, module_id: ModuleId, name: Name, mac: MacroId) {
710 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
712 }
713
714 fn define_macro_def(
718 &mut self,
719 module_id: ModuleId,
720 name: Name,
721 macro_: Macro2Id,
722 vis: &RawVisibility,
723 ) {
724 let vis = self
725 .def_map
726 .resolve_visibility(
727 self.crate_local_def_map.unwrap_or(&self.local_def_map),
728 self.db,
729 module_id,
730 vis,
731 false,
732 )
733 .unwrap_or(Visibility::Public);
734 self.def_map.modules[module_id].scope.declare(macro_.into());
735 self.update(
736 module_id,
737 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
738 vis,
739 None,
740 );
741 }
742
743 fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
748 let module_id = self.def_map.root;
749 self.def_map.modules[module_id].scope.declare(macro_.into());
750 self.update(
751 module_id,
752 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
753 Visibility::Public,
754 None,
755 );
756 }
757
758 fn import_macros_from_extern_crate(
765 &mut self,
766 krate: Crate,
767 names: Option<Vec<Name>>,
768 extern_crate: Option<ExternCrateId>,
769 ) {
770 let def_map = crate_def_map(self.db, krate);
771 let root_scope = &def_map[def_map.root].scope;
774 match names {
775 Some(names) => {
776 for name in names {
777 if let Some(def) = root_scope.get(&name).take_macros() {
779 self.def_map.macro_use_prelude.insert(name, (def, extern_crate));
780 }
781 }
782 }
783 None => {
784 for (name, it) in root_scope.macros() {
785 self.def_map.macro_use_prelude.insert(name.clone(), (it.def, extern_crate));
786 }
787 }
788 }
789 }
790
791 fn resolve_imports(&mut self) -> ReachedFixedPoint {
793 let mut res = ReachedFixedPoint::Yes;
794 let imports = mem::take(&mut self.unresolved_imports);
795
796 self.unresolved_imports = imports
797 .into_iter()
798 .filter_map(|mut directive| {
799 directive.status = self.resolve_import(directive.module_id, &directive.import);
800 match directive.status {
801 PartialResolvedImport::Indeterminate(resolved) => {
802 self.record_resolved_import(&directive);
803 self.indeterminate_imports.push((directive, resolved));
804 res = ReachedFixedPoint::No;
805 None
806 }
807 PartialResolvedImport::Resolved(_) => {
808 self.record_resolved_import(&directive);
809 res = ReachedFixedPoint::No;
810 None
811 }
812 PartialResolvedImport::Unresolved => Some(directive),
813 }
814 })
815 .collect();
816
817 let mut indeterminate_imports = std::mem::take(&mut self.indeterminate_imports);
822 indeterminate_imports.retain_mut(|(directive, partially_resolved)| {
823 let partially_resolved = partially_resolved.availability();
824 directive.status = self.resolve_import(directive.module_id, &directive.import);
825 match directive.status {
826 PartialResolvedImport::Indeterminate(import)
827 if partially_resolved != import.availability() =>
828 {
829 self.record_resolved_import(directive);
830 res = ReachedFixedPoint::No;
831 false
832 }
833 PartialResolvedImport::Resolved(_) => {
834 self.record_resolved_import(directive);
835 res = ReachedFixedPoint::No;
836 false
837 }
838 _ => true,
839 }
840 });
841 self.indeterminate_imports = indeterminate_imports;
842
843 res
844 }
845
846 fn resolve_import(&self, module_id: ModuleId, import: &Import) -> PartialResolvedImport {
847 let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db, Edition::LATEST))
848 .entered();
849 tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
850 let ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info } =
851 self.def_map.resolve_path_fp_with_macro(
852 self.crate_local_def_map.unwrap_or(&self.local_def_map),
853 self.db,
854 ResolveMode::Import,
855 module_id,
856 &import.path,
857 BuiltinShadowMode::Module,
858 None, );
860
861 if reached_fixedpoint == ReachedFixedPoint::No
862 || resolved_def.is_none()
863 || segment_index.is_some()
864 {
865 return PartialResolvedImport::Unresolved;
866 }
867
868 if prefix_info.differing_crate {
869 return PartialResolvedImport::Resolved(
870 resolved_def.filter_visibility(|v| matches!(v, Visibility::Public)),
871 );
872 }
873
874 if resolved_def.is_full() {
876 PartialResolvedImport::Resolved(resolved_def)
877 } else {
878 PartialResolvedImport::Indeterminate(resolved_def)
879 }
880 }
881
882 fn record_resolved_import(&mut self, directive: &ImportDirective) {
883 let _p = tracing::info_span!("record_resolved_import").entered();
884
885 let module_id = directive.module_id;
886 let import = &directive.import;
887 let mut def = directive.status.namespaces();
888 let vis = self
889 .def_map
890 .resolve_visibility(
891 self.crate_local_def_map.unwrap_or(&self.local_def_map),
892 self.db,
893 module_id,
894 &directive.import.visibility,
895 false,
896 )
897 .unwrap_or(Visibility::Public);
898
899 match import.source {
900 ImportSource {
901 kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly),
902 id,
903 use_tree,
904 ..
905 } => {
906 let name = match &import.alias {
907 Some(ImportAlias::Alias(name)) => Some(name),
908 Some(ImportAlias::Underscore) => None,
909 None => match import.path.segments().last() {
910 Some(last_segment) => Some(last_segment),
911 None => {
912 cov_mark::hit!(bogus_paths);
913 return;
914 }
915 },
916 };
917
918 if kind == ImportKind::TypeOnly {
919 def.values = None;
920 def.macros = None;
921 }
922 let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
923 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
924
925 if let Some(def) = def.types.as_mut() {
932 let is_extern_crate_reimport_without_prefix = || {
933 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
934 return false;
935 };
936 if kind == ImportKind::Glob {
937 return false;
938 }
939 matches!(import.path.kind, PathKind::Plain | PathKind::SELF)
940 && import.path.segments().len() < 2
941 };
942 if is_extern_crate_reimport_without_prefix() {
943 def.vis = vis;
944 }
945 }
946
947 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
948 }
949 ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree, .. } => {
950 tracing::debug!("glob import: {:?}", import);
951 let glob = GlobId { use_: id, idx: use_tree };
952 match def.take_types() {
953 Some(ModuleDefId::ModuleId(m)) => {
954 if is_prelude {
955 cov_mark::hit!(std_prelude);
958 self.def_map.prelude = Some((m, Some(id)));
959 } else if m.krate(self.db) != self.def_map.krate {
960 cov_mark::hit!(glob_across_crates);
961 let scope = &m.def_map(self.db)[m].scope;
963
964 let items = scope
966 .resolutions()
967 .map(|(n, res)| {
969 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
970 })
971 .filter(|(_, res)| !res.is_none())
972 .collect::<Vec<_>>();
973
974 self.update(
975 module_id,
976 &items,
977 vis,
978 Some(ImportOrExternCrate::Glob(glob)),
979 );
980 } else {
981 let scope = if m.block(self.db) == self.def_map.block_id() {
985 &self.def_map[m].scope
986 } else {
987 &m.def_map(self.db)[m].scope
988 };
989
990 let items = scope
992 .resolutions()
993 .map(|(n, res)| {
995 (
996 n,
997 res.filter_visibility(|v| {
998 v.is_visible_from_def_map(
999 self.db,
1000 &self.def_map,
1001 module_id,
1002 )
1003 }),
1004 )
1005 })
1006 .filter(|(_, res)| !res.is_none())
1007 .collect::<Vec<_>>();
1008
1009 self.update(
1010 module_id,
1011 &items,
1012 vis,
1013 Some(ImportOrExternCrate::Glob(glob)),
1014 );
1015 let glob_imports = self.glob_imports.entry(m).or_default();
1017 match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
1018 None => glob_imports.push((module_id, vis, glob)),
1019 Some((_, old_vis, _)) => {
1020 if let Some(new_vis) = old_vis.max(self.db, vis, &self.def_map)
1021 {
1022 *old_vis = new_vis;
1023 }
1024 }
1025 }
1026 }
1027 }
1028 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
1029 cov_mark::hit!(glob_enum);
1030 let resolutions = e
1032 .enum_variants(self.db)
1033 .variants
1034 .iter()
1035 .map(|(name, &(variant, shape))| {
1036 let res = if shape.has_value_ns_ctor() {
1038 PerNs::both(variant.into(), variant.into(), vis, None)
1039 } else {
1040 PerNs::types(variant.into(), vis, None)
1041 };
1042 (Some(name.clone()), res)
1043 })
1044 .collect::<Vec<_>>();
1045 self.update(
1046 module_id,
1047 &resolutions,
1048 vis,
1049 Some(ImportOrExternCrate::Glob(glob)),
1050 );
1051 }
1052 Some(ModuleDefId::TraitId(it)) => {
1053 let resolutions = if true {
1060 vec![]
1061 } else {
1062 TraitItems::query(self.db, it)
1063 .items
1064 .iter()
1065 .map(|&(ref name, variant)| {
1066 let res = match variant {
1067 AssocItemId::FunctionId(it) => {
1068 PerNs::values(it.into(), vis, None)
1069 }
1070 AssocItemId::ConstId(it) => {
1071 PerNs::values(it.into(), vis, None)
1072 }
1073 AssocItemId::TypeAliasId(it) => {
1074 PerNs::types(it.into(), vis, None)
1075 }
1076 };
1077 (Some(name.clone()), res)
1078 })
1079 .collect::<Vec<_>>()
1080 };
1081 self.update(
1082 module_id,
1083 &resolutions,
1084 vis,
1085 Some(ImportOrExternCrate::Glob(glob)),
1086 );
1087 }
1088 Some(d) => {
1089 tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
1090 }
1091 None => {
1092 tracing::debug!("glob import {:?} didn't resolve as type", import);
1093 }
1094 }
1095 }
1096 }
1097 }
1098
1099 fn update(
1100 &mut self,
1101 module_id: ModuleId,
1103 resolutions: &[(Option<Name>, PerNs)],
1104 vis: Visibility,
1106 import: Option<ImportOrExternCrate>,
1107 ) {
1108 self.update_recursive(module_id, resolutions, vis, import, 0)
1109 }
1110
1111 fn update_recursive(
1112 &mut self,
1113 module_id: ModuleId,
1115 resolutions: &[(Option<Name>, PerNs)],
1116 vis: Visibility,
1119 import: Option<ImportOrExternCrate>,
1120 depth: usize,
1121 ) {
1122 if depth > GLOB_RECURSION_LIMIT {
1123 panic!("infinite recursion in glob imports!");
1125 }
1126 let mut changed = false;
1127
1128 for (name, res) in resolutions {
1129 match name {
1130 Some(name) => {
1131 changed |=
1132 self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
1133 }
1134 None => {
1135 let (tr, import) = match res.take_types_full() {
1136 Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
1137 (tr, import)
1138 }
1139 Some(other) => {
1140 tracing::debug!("non-trait `_` import of {:?}", other);
1141 continue;
1142 }
1143 None => continue,
1144 };
1145 let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
1146 let should_update = match old_vis {
1147 None => true,
1148 Some(old_vis) => {
1149 let max_vis = old_vis.max(self.db, vis, &self.def_map).unwrap_or_else(|| {
1150 panic!("`Tr as _` imports with unrelated visibilities {old_vis:?} and {vis:?} (trait {tr:?})");
1151 });
1152
1153 if max_vis == old_vis {
1154 false
1155 } else {
1156 cov_mark::hit!(upgrade_underscore_visibility);
1157 true
1158 }
1159 }
1160 };
1161
1162 if should_update {
1163 changed = true;
1164 self.def_map.modules[module_id].scope.push_unnamed_trait(
1165 tr,
1166 vis,
1167 import.and_then(ImportOrExternCrate::import),
1168 );
1169 }
1170 }
1171 }
1172 }
1173
1174 if !changed {
1175 return;
1176 }
1177 let glob_imports = self
1178 .glob_imports
1179 .get(&module_id)
1180 .into_iter()
1181 .flatten()
1182 .filter(|(glob_importing_module, _, _)| {
1183 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
1186 })
1187 .cloned()
1188 .collect::<Vec<_>>();
1189
1190 for (glob_importing_module, glob_import_vis, glob) in glob_imports {
1191 let vis = glob_import_vis.min(self.db, vis, &self.def_map).unwrap_or(glob_import_vis);
1192 self.update_recursive(
1193 glob_importing_module,
1194 resolutions,
1195 vis,
1196 Some(ImportOrExternCrate::Glob(glob)),
1197 depth + 1,
1198 );
1199 }
1200 }
1201
1202 fn push_res_and_update_glob_vis(
1203 &mut self,
1204 module_id: ModuleId,
1205 name: &Name,
1206 mut defs: PerNs,
1207 vis: Visibility,
1208 def_import_type: Option<ImportOrExternCrate>,
1209 ) -> bool {
1210 if let Some(def) = defs.types.as_mut() {
1211 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1212 }
1213 if let Some(def) = defs.values.as_mut() {
1214 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1215 }
1216 if let Some(def) = defs.macros.as_mut() {
1217 def.vis = def.vis.min(self.db, vis, &self.def_map).unwrap_or(vis);
1218 }
1219
1220 let mut changed = false;
1221
1222 if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
1223 let prev_defs = self.def_map[module_id].scope.get(name);
1224
1225 if let Some(def) = defs.types
1229 && let Some(prev_def) = prev_defs.types
1230 {
1231 if def.def == prev_def.def
1232 && self.from_glob_import.contains_type(module_id, name.clone())
1233 && def.vis != prev_def.vis
1234 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1235 {
1236 changed = true;
1237 defs.types = None;
1240 self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
1241 }
1242 else if def.def != prev_def.def && prev_def.import == def_import_type {
1251 changed = true;
1252 defs.types = None;
1253 self.def_map.modules[module_id].scope.update_def_types(name, def.def, def.vis);
1254 }
1255 }
1256
1257 if let Some(def) = defs.values
1258 && let Some(prev_def) = prev_defs.values
1259 {
1260 if def.def == prev_def.def
1261 && self.from_glob_import.contains_value(module_id, name.clone())
1262 && def.vis != prev_def.vis
1263 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1264 {
1265 changed = true;
1266 defs.values = None;
1267 self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
1268 } else if def.def != prev_def.def
1269 && prev_def.import.map(ImportOrExternCrate::from) == def_import_type
1270 {
1271 changed = true;
1272 defs.values = None;
1273 self.def_map.modules[module_id].scope.update_def_values(name, def.def, def.vis);
1274 }
1275 }
1276
1277 if let Some(def) = defs.macros
1278 && let Some(prev_def) = prev_defs.macros
1279 {
1280 if def.def == prev_def.def
1281 && self.from_glob_import.contains_macro(module_id, name.clone())
1282 && def.vis != prev_def.vis
1283 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1284 {
1285 changed = true;
1286 defs.macros = None;
1287 self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
1288 } else if def.def != prev_def.def && prev_def.import == def_import_type {
1289 changed = true;
1290 defs.macros = None;
1291 self.def_map.modules[module_id].scope.update_def_macros(name, def.def, def.vis);
1292 }
1293 }
1294 }
1295
1296 changed |= self.def_map.modules[module_id].scope.push_res_with_import(
1297 &mut self.from_glob_import,
1298 (module_id, name.clone()),
1299 defs,
1300 def_import_type,
1301 );
1302
1303 changed
1304 }
1305
1306 fn resolve_macros(&mut self) -> ReachedFixedPoint {
1307 let mut macros = mem::take(&mut self.unresolved_macros);
1308 let mut resolved = Vec::new();
1309 let push_resolved = |resolved: &mut Vec<_>, directive: &MacroDirective<'_>, call_id| {
1310 let attr_macro_item = match &directive.kind {
1311 MacroDirectiveKind::Attr { ast_id, .. } => Some(ast_id.ast_id),
1312 MacroDirectiveKind::FnLike { .. } | MacroDirectiveKind::Derive { .. } => None,
1313 };
1314 resolved.push((
1315 directive.module_id,
1316 directive.depth,
1317 directive.container,
1318 call_id,
1319 attr_macro_item,
1320 ));
1321 };
1322
1323 #[derive(PartialEq, Eq)]
1324 enum Resolved {
1325 Yes,
1326 No,
1327 }
1328
1329 let mut eager_callback_buffer = vec![];
1330 let mut res = ReachedFixedPoint::Yes;
1331 let mut retain = |directive: &MacroDirective<'db>| {
1333 let subns = match &directive.kind {
1334 MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
1335 MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
1336 MacroSubNs::Attr
1337 }
1338 };
1339 let resolver = |def_map: &DefMap, path: &_| {
1340 let resolved_res = def_map.resolve_path_fp_with_macro(
1341 self.crate_local_def_map.unwrap_or(&self.local_def_map),
1342 self.db,
1343 ResolveMode::Other,
1344 directive.module_id,
1345 path,
1346 BuiltinShadowMode::Module,
1347 Some(subns),
1348 );
1349 resolved_res.resolved_def.take_macros().map(|it| (it, it.definition(self.db)))
1350 };
1351 let resolver_def_id = |path: &_| resolver(&self.def_map, path).map(|(_, it)| it);
1352
1353 match &directive.kind {
1354 MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1355 let call_id = macro_call_as_call_id(
1356 self.db,
1357 ast_id.ast_id,
1358 &ast_id.path,
1359 *call_site,
1360 *expand_to,
1361 self.def_map.krate,
1362 directive.depth,
1363 self.def_map.recursion_limit(),
1364 resolver_def_id,
1365 &mut |ptr, call_id| {
1366 eager_callback_buffer.push((directive.module_id, ptr, call_id));
1367 },
1368 );
1369 if let Ok(call_id) = call_id {
1370 if let Some(call_id) = call_id.value {
1372 self.def_map.modules[directive.module_id]
1373 .scope
1374 .add_macro_invoc(ast_id.ast_id, call_id);
1375
1376 push_resolved(&mut resolved, directive, call_id);
1377
1378 res = ReachedFixedPoint::No;
1379 return Resolved::Yes;
1380 }
1381 }
1382 }
1383 MacroDirectiveKind::Derive {
1384 ast_id,
1385 derive_attr,
1386 derive_pos,
1387 ctxt: call_site,
1388 derive_macro_id,
1389 } => {
1390 let id = derive_macro_as_call_id(
1392 self.db,
1393 ast_id,
1394 *derive_attr,
1395 *derive_pos as u32,
1396 *call_site,
1397 self.def_map.krate,
1398 |path| resolver(&self.def_map, path),
1399 *derive_macro_id,
1400 directive.depth,
1401 );
1402
1403 if let Ok((macro_id, def_id, call_id)) = id {
1404 self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1405 ast_id.ast_id,
1406 Either::Left(call_id),
1407 *derive_attr,
1408 *derive_pos,
1409 );
1410 if def_id.krate != self.def_map.krate {
1412 let def_map = crate_def_map(self.db, def_id.krate);
1413 if let Some(helpers) = def_map.data.exported_derives.get(¯o_id) {
1414 self.def_map
1415 .derive_helpers_in_scope
1416 .entry(ast_id.ast_id.map(|it| it.upcast()))
1417 .or_default()
1418 .extend(izip!(
1419 helpers.iter().cloned(),
1420 iter::repeat(macro_id),
1421 iter::repeat(Either::Left(call_id)),
1422 ));
1423 }
1424 }
1425
1426 push_resolved(&mut resolved, directive, call_id);
1427
1428 res = ReachedFixedPoint::No;
1429 return Resolved::Yes;
1430 }
1431 }
1432 MacroDirectiveKind::Attr {
1433 ast_id: file_ast_id,
1434 mod_item,
1435 attr_id,
1436 attr,
1437 tree,
1438 item_tree,
1439 } => {
1440 let &AstIdWithPath { ast_id, ref path } = file_ast_id;
1441 let file_id = ast_id.file_id;
1442
1443 let mut recollect_without = |collector: &mut Self| {
1444 let mod_dir = collector.mod_dirs[&directive.module_id].clone();
1446 collector.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr_id);
1447
1448 ModCollector {
1449 def_collector: collector,
1450 macro_depth: directive.depth,
1451 module_id: directive.module_id,
1452 tree_id: *tree,
1453 item_tree,
1454 mod_dir,
1455 }
1456 .collect(&[*mod_item], directive.container);
1457 res = ReachedFixedPoint::No;
1458 Resolved::Yes
1459 };
1460
1461 if let Some(ident) = path.as_ident()
1462 && let Some(helpers) = self.def_map.derive_helpers_in_scope.get(&ast_id)
1463 && helpers.iter().any(|(it, ..)| it == ident)
1464 {
1465 cov_mark::hit!(resolved_derive_helper);
1466 return recollect_without(self);
1469 }
1470
1471 let def = match resolver_def_id(path) {
1472 Some(def) if def.is_attribute() => def,
1473 _ => return Resolved::No,
1474 };
1475
1476 if matches!(
1483 def.kind,
1484 MacroDefKind::BuiltInAttr(_, expander)
1485 if expander.is_test() || expander.is_bench() || expander.is_test_case()
1486 ) {
1487 let test_is_active = self.cfg_options.check_atom(&CfgAtom::Flag(sym::test));
1488 if test_is_active {
1489 return recollect_without(self);
1490 }
1491 }
1492
1493 let mut call_id = || {
1494 let active_attrs = self.prev_active_attrs.entry(ast_id).or_default();
1495 active_attrs.push(*attr_id);
1496
1497 attr_macro_as_call_id(
1498 self.db,
1499 file_ast_id,
1500 attr,
1501 AttrMacroAttrIds::from_many(active_attrs),
1502 self.def_map.krate,
1503 def,
1504 directive.depth,
1505 )
1506 };
1507 if matches!(def,
1508 MacroDefId { kind: MacroDefKind::BuiltInAttr(_, exp), .. }
1509 if exp.is_derive()
1510 ) {
1511 let ast_adt_id: FileAstId<ast::Adt> = match item_tree.index(*mod_item) {
1516 ModItemKind::Struct(ast_id, _) => ast_id.upcast(),
1517 ModItemKind::Union(ast_id, _) => ast_id.upcast(),
1518 ModItemKind::Enum(ast_id, _) => ast_id.upcast(),
1519 _ => {
1520 let diag = DefDiagnostic::invalid_derive_target(
1521 directive.module_id,
1522 ast_id,
1523 *attr_id,
1524 );
1525 self.def_map.diagnostics.push(diag);
1526 return recollect_without(self);
1527 }
1528 };
1529
1530 let ast_id = ast_id.with_value(ast_adt_id);
1531
1532 let mut derive_call_ids = SmallVec::new();
1533 match attr.parse_path_comma_token_tree(self.db) {
1534 Some(derive_macros) => {
1535 let call_id = call_id();
1536 for (idx, (path, call_site, _)) in derive_macros.enumerate() {
1537 let ast_id = AstIdWithPath::new(
1538 file_id,
1539 ast_id.value,
1540 Interned::new(path),
1541 );
1542
1543 derive_call_ids.push(None);
1544
1545 let id = derive_macro_as_call_id(
1549 self.db,
1550 &ast_id,
1551 *attr_id,
1552 idx as u32,
1553 call_site.ctx,
1554 self.def_map.krate,
1555 |path| resolver(&self.def_map, path),
1556 call_id,
1557 directive.depth,
1558 );
1559
1560 let ast_id_without_path = ast_id.ast_id;
1561 let directive = MacroDirective {
1562 module_id: directive.module_id,
1563 depth: directive.depth + 1,
1564 kind: MacroDirectiveKind::Derive {
1565 ast_id,
1566 derive_attr: *attr_id,
1567 derive_pos: idx,
1568 ctxt: call_site.ctx,
1569 derive_macro_id: call_id,
1570 },
1571 container: directive.container,
1572 };
1573
1574 if let Ok((macro_id, def_id, call_id)) = id {
1575 let (mut helpers_start, mut helpers_end) = (0, 0);
1576 if def_id.krate != self.def_map.krate {
1578 let def_map = crate_def_map(self.db, def_id.krate);
1579 if let Some(helpers) =
1580 def_map.data.exported_derives.get(¯o_id)
1581 {
1582 let derive_helpers = self
1583 .def_map
1584 .derive_helpers_in_scope
1585 .entry(
1586 ast_id_without_path.map(|it| it.upcast()),
1587 )
1588 .or_default();
1589 helpers_start = derive_helpers.len();
1590 derive_helpers.extend(izip!(
1591 helpers.iter().cloned(),
1592 iter::repeat(macro_id),
1593 iter::repeat(Either::Left(call_id)),
1594 ));
1595 helpers_end = derive_helpers.len();
1596 }
1597 }
1598
1599 if super::enable_builtin_derive_fast_path()
1600 && let MacroDefKind::BuiltInDerive(_, builtin_derive) =
1601 def_id.kind
1602 && crate::builtin_derive::has_builtin_derive_impl(
1603 builtin_derive,
1604 )
1605 {
1606 self.deferred_builtin_derives
1607 .entry(ast_id_without_path.upcast())
1608 .or_default()
1609 .push(DeferredBuiltinDerive {
1610 call_id,
1611 derive: builtin_derive,
1612 module_id: directive.module_id,
1613 container: directive.container,
1614 depth: directive.depth,
1615 derive_attr_id: *attr_id,
1616 derive_index: idx as u32,
1617 helpers_range: helpers_start..helpers_end,
1618 });
1619 } else {
1620 push_resolved(&mut resolved, &directive, call_id);
1621 *derive_call_ids.last_mut().unwrap() =
1622 Some(Either::Left(call_id));
1623 }
1624 } else {
1625 self.unresolved_macros.push(directive);
1626 }
1627 }
1628
1629 self.def_map.modules[directive.module_id]
1634 .scope
1635 .init_derive_attribute(
1636 ast_id,
1637 *attr_id,
1638 call_id,
1639 derive_call_ids,
1640 );
1641 }
1642 None => {
1643 let diag = DefDiagnostic::malformed_derive(
1644 directive.module_id,
1645 ast_id,
1646 *attr_id,
1647 );
1648 self.def_map.diagnostics.push(diag);
1649 }
1650 }
1651
1652 return recollect_without(self);
1653 }
1654
1655 if let MacroDefKind::ProcMacro(_, exp, _) = def.kind {
1656 if let Some(err) = exp.as_expand_error(def.krate) {
1661 self.def_map.diagnostics.push(DefDiagnostic::macro_error(
1662 directive.module_id,
1663 ast_id,
1664 (**path).clone(),
1665 err,
1666 ));
1667 return recollect_without(self);
1668 }
1669 }
1670
1671 if let Some(deferred_derives) = self.deferred_builtin_derives.remove(&ast_id) {
1673 resolved.extend(deferred_derives.into_iter().map(|derive| {
1674 (
1675 derive.module_id,
1676 derive.depth,
1677 derive.container,
1678 derive.call_id,
1679 Some(ast_id),
1680 )
1681 }));
1682 }
1683
1684 let call_id = call_id();
1685 self.def_map.modules[directive.module_id]
1686 .scope
1687 .add_attr_macro_invoc(ast_id, call_id);
1688
1689 push_resolved(&mut resolved, directive, call_id);
1690 res = ReachedFixedPoint::No;
1691 return Resolved::Yes;
1692 }
1693 }
1694
1695 Resolved::No
1696 };
1697 macros.retain(|it| retain(it) == Resolved::No);
1698 macros.extend(mem::take(&mut self.unresolved_macros));
1700 self.unresolved_macros = macros;
1701
1702 for (module_id, ptr, call_id) in eager_callback_buffer {
1703 self.def_map.modules[module_id].scope.add_macro_invoc(ptr.map(|(_, it)| it), call_id);
1704 }
1705
1706 for (module_id, depth, container, macro_call_id, attr_macro_item) in resolved {
1707 self.collect_macro_expansion(
1708 module_id,
1709 macro_call_id,
1710 depth,
1711 container,
1712 attr_macro_item,
1713 );
1714 }
1715
1716 res
1717 }
1718
1719 fn collect_macro_expansion(
1720 &mut self,
1721 module_id: ModuleId,
1722 macro_call_id: MacroCallId,
1723 depth: u32,
1724 container: ItemContainerId,
1725 attr_macro_item: Option<AstId<ast::Item>>,
1726 ) {
1727 if depth > self.def_map.recursion_limit() {
1728 cov_mark::hit!(macro_expansion_overflow);
1729 tracing::warn!("macro expansion is too deep");
1730 return;
1731 }
1732 let file_id = macro_call_id.into();
1733
1734 let item_tree = file_item_tree(self.db, file_id, self.def_map.krate);
1735
1736 if let Some(attr_macro_item) = attr_macro_item
1752 && let Some(derive_helpers) = self.def_map.derive_helpers_in_scope.get(&attr_macro_item)
1753 {
1754 let derive_helpers = derive_helpers.clone();
1755 for item in item_tree.top_level_items() {
1756 self.def_map
1757 .derive_helpers_in_scope
1758 .entry(InFile::new(file_id, item.ast_id(item_tree)))
1759 .or_default()
1760 .extend(derive_helpers.iter().cloned());
1761 }
1762 }
1763
1764 let mod_dir = if macro_call_id.is_include_macro(self.db) {
1765 ModDir::root()
1766 } else {
1767 self.mod_dirs[&module_id].clone()
1768 };
1769
1770 ModCollector {
1771 def_collector: &mut *self,
1772 macro_depth: depth,
1773 tree_id: TreeId::new(file_id, None),
1774 module_id,
1775 item_tree,
1776 mod_dir,
1777 }
1778 .collect(item_tree.top_level_items(), container);
1779 }
1780
1781 fn finish(mut self) -> (DefMap, LocalDefMap) {
1782 let _p = tracing::info_span!("DefCollector::finish").entered();
1784
1785 for directive in &self.unresolved_macros {
1786 match &directive.kind {
1787 MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
1788 let macro_call_as_call_id = macro_call_as_call_id(
1790 self.db,
1791 ast_id.ast_id,
1792 &ast_id.path,
1793 *call_site,
1794 *expand_to,
1795 self.def_map.krate,
1796 directive.depth,
1797 self.def_map.recursion_limit(),
1798 |path| {
1799 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1800 self.crate_local_def_map.unwrap_or(&self.local_def_map),
1801 self.db,
1802 ResolveMode::Other,
1803 directive.module_id,
1804 path,
1805 BuiltinShadowMode::Module,
1806 Some(MacroSubNs::Bang),
1807 );
1808 resolved_res.resolved_def.take_macros().map(|it| it.definition(self.db))
1809 },
1810 &mut |_, _| (),
1811 );
1812 if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
1813 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1814 directive.module_id,
1815 MacroCallKind::FnLike {
1816 ast_id: ast_id.ast_id,
1817 expand_to: *expand_to,
1818 eager: None,
1819 },
1820 path,
1821 ));
1822 }
1823 }
1824 MacroDirectiveKind::Derive {
1825 ast_id,
1826 derive_attr,
1827 derive_pos,
1828 derive_macro_id,
1829 ..
1830 } => {
1831 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1832 directive.module_id,
1833 MacroCallKind::Derive {
1834 ast_id: ast_id.ast_id,
1835 derive_attr_index: *derive_attr,
1836 derive_index: *derive_pos as u32,
1837 derive_macro_id: *derive_macro_id,
1838 },
1839 (*ast_id.path).clone(),
1840 ));
1841 }
1842 MacroDirectiveKind::Attr { .. } => {}
1844 }
1845 }
1846
1847 for import in &self.unresolved_imports {
1849 let &ImportDirective {
1850 module_id,
1851 import:
1852 Import {
1853 ref path,
1854 source: ImportSource { use_tree, id, is_prelude: _, kind: _ },
1855 ..
1856 },
1857 ..
1858 } = import;
1859 if matches!(
1860 (path.segments().first(), &path.kind),
1861 (Some(krate), PathKind::Plain | PathKind::Abs) if self.unresolved_extern_crates.contains(krate)
1862 ) {
1863 continue;
1864 }
1865 let item_tree_id = id.lookup(self.db).id;
1866 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1867 module_id,
1868 item_tree_id,
1869 use_tree,
1870 ));
1871 }
1872
1873 always!(
1874 self.deferred_builtin_derives.is_empty(),
1875 "self.deferred_builtin_derives={:#?}",
1876 self.deferred_builtin_derives,
1877 );
1878
1879 (self.def_map, self.local_def_map)
1880 }
1881}
1882
1883struct ModCollector<'a, 'db> {
1885 def_collector: &'a mut DefCollector<'db>,
1886 macro_depth: u32,
1887 module_id: ModuleId,
1888 tree_id: TreeId,
1889 item_tree: &'db ItemTree,
1890 mod_dir: ModDir,
1891}
1892
1893impl ModCollector<'_, '_> {
1894 fn collect_in_top_module(&mut self, items: &[ModItemId]) {
1895 self.collect(items, self.module_id.into())
1896 }
1897
1898 fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) {
1899 let is_crate_root = self.module_id == self.def_collector.def_map.root
1900 && self.def_collector.def_map.block.is_none();
1901
1902 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1905
1906 let db = self.def_collector.db;
1907 let module_id = self.module_id;
1908 let consider_deferred_derives =
1909 |file_id: HirFileId,
1910 deferred_derives: &mut FxHashMap<_, Vec<DeferredBuiltinDerive>>,
1911 ast_id: FileAstId<ast::Adt>,
1912 id: AdtId,
1913 def_map: &mut DefMap| {
1914 let ast_id = InFile::new(file_id, ast_id.upcast());
1915 let Some(deferred_derives) = deferred_derives.remove(&ast_id.upcast()) else {
1916 return;
1917 };
1918 let module = &mut def_map.modules[module_id];
1919 for deferred_derive in deferred_derives {
1920 crate::builtin_derive::with_derive_traits(deferred_derive.derive, |trait_| {
1921 let impl_id = BuiltinDeriveImplId::new(
1922 db,
1923 BuiltinDeriveImplLoc {
1924 adt: id,
1925 trait_,
1926 derive_attr_id: deferred_derive.derive_attr_id,
1927 derive_index: deferred_derive.derive_index,
1928 },
1929 );
1930 module.scope.define_builtin_derive_impl(impl_id);
1931 module.scope.set_derive_macro_invoc(
1932 ast_id,
1933 Either::Right(impl_id),
1934 deferred_derive.derive_attr_id,
1935 deferred_derive.derive_index as usize,
1936 );
1937 if let Some(derive_helpers) =
1939 def_map.derive_helpers_in_scope.get_mut(&ast_id.map(|it| it.upcast()))
1940 {
1941 for (_, _, call_id) in
1942 &mut derive_helpers[deferred_derive.helpers_range.clone()]
1943 {
1944 *call_id = Either::Right(impl_id);
1945 }
1946 }
1947 });
1948 }
1949 };
1950 let update_def =
1951 |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, value_ns_ctor_vis| {
1952 def_collector.def_map.modules[module_id].scope.declare(id);
1953 def_collector.update(
1954 module_id,
1955 &[(Some(name.clone()), PerNs::from_def(id, vis, value_ns_ctor_vis, None))],
1956 vis,
1957 None,
1958 )
1959 };
1960 let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| {
1961 def_map
1962 .resolve_visibility(local_def_map, db, module_id, visibility, false)
1963 .unwrap_or(Visibility::Public)
1964 };
1965
1966 let item_tree = self.item_tree;
1967
1968 let mut process_mod_item = |item_id: ModItemId| {
1969 let attrs = match self.item_tree.attrs(item_id) {
1970 Some(AttrsOrCfg::Enabled { attrs }) => attrs.as_ref(),
1971 None => Attrs::EMPTY,
1972 Some(AttrsOrCfg::CfgDisabled(cfg)) => {
1973 let ast_id = item_id.ast_id(self.item_tree).erase();
1974 self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg.0);
1975 return;
1976 }
1977 };
1978
1979 if let Err(()) = self.resolve_attributes(attrs, item_id, container) {
1980 return;
1983 }
1984
1985 let def_map = &mut self.def_collector.def_map;
1986 let local_def_map =
1987 self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map);
1988
1989 match self.item_tree.index(item_id) {
1990 ModItemKind::Mod(ast_id, module) => self.collect_module(ast_id, module, attrs),
1991 ModItemKind::Use(ast_id, use_) => {
1992 let id =
1993 UseLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
1994 .intern(db);
1995 let is_prelude = attrs.by_key(sym::prelude_import).exists();
1996 Import::from_use(self.item_tree, use_, id, is_prelude, |import| {
1997 self.def_collector.unresolved_imports.push(ImportDirective {
1998 module_id: self.module_id,
1999 import,
2000 status: PartialResolvedImport::Unresolved,
2001 });
2002 })
2003 }
2004 ModItemKind::ExternCrate(ast_id, item) => {
2005 let item_tree::ExternCrate { name, visibility, alias } = item;
2006
2007 let id = ExternCrateLoc {
2008 container: module_id,
2009 id: InFile::new(self.tree_id.file_id(), ast_id),
2010 }
2011 .intern(db);
2012 def_map.modules[self.module_id].scope.define_extern_crate_decl(id);
2013
2014 let is_self = *name == sym::self_;
2015 let resolved = if is_self {
2016 cov_mark::hit!(extern_crate_self_as);
2017 Some(def_map.crate_root(db))
2018 } else {
2019 self.def_collector
2020 .deps
2021 .get(name)
2022 .map(|dep| crate_def_map(db, dep.crate_id).root_module_id())
2023 };
2024
2025 let name = match alias {
2026 Some(ImportAlias::Alias(name)) => Some(name),
2027 Some(ImportAlias::Underscore) => None,
2028 None => Some(name),
2029 };
2030
2031 if let Some(resolved) = resolved {
2032 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]);
2033
2034 if is_crate_root {
2035 if let Some(name) = name {
2037 self.def_collector
2038 .local_def_map
2039 .extern_prelude
2040 .insert(name.clone(), (resolved, Some(id)));
2041 }
2042 if !is_self {
2044 self.process_macro_use_extern_crate(
2045 id,
2046 attrs.by_key(sym::macro_use).attrs(),
2047 resolved.krate(self.def_collector.db),
2048 );
2049 }
2050 }
2051
2052 self.def_collector.update(
2053 module_id,
2054 &[(
2055 name.cloned(),
2056 PerNs::types(
2057 resolved.into(),
2058 vis,
2059 Some(ImportOrExternCrate::ExternCrate(id)),
2060 ),
2061 )],
2062 vis,
2063 Some(ImportOrExternCrate::ExternCrate(id)),
2064 );
2065 } else {
2066 if let Some(name) = name {
2067 self.def_collector.unresolved_extern_crates.insert(name.clone());
2068 }
2069 self.def_collector.def_map.diagnostics.push(
2070 DefDiagnostic::unresolved_extern_crate(
2071 module_id,
2072 InFile::new(self.file_id(), ast_id),
2073 ),
2074 );
2075 }
2076 }
2077 ModItemKind::ExternBlock(ast_id, block) => {
2078 let extern_block_id = ExternBlockLoc {
2079 container: module_id,
2080 id: InFile::new(self.file_id(), ast_id),
2081 }
2082 .intern(db);
2083 self.def_collector.def_map.modules[self.module_id]
2084 .scope
2085 .define_extern_block(extern_block_id);
2086 self.collect(&block.children, ItemContainerId::ExternBlockId(extern_block_id))
2087 }
2088 ModItemKind::MacroCall(ast_id, mac) => {
2089 self.collect_macro_call(ast_id, mac, container)
2090 }
2091 ModItemKind::MacroRules(ast_id, mac) => {
2092 self.collect_macro_rules(attrs, ast_id, mac, module_id)
2093 }
2094 ModItemKind::Macro2(ast_id, mac) => {
2095 self.collect_macro_def(attrs, ast_id, mac, module_id)
2096 }
2097 ModItemKind::Impl(ast_id, imp) => {
2098 let impl_id =
2099 ImplLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
2100 .intern(db);
2101 self.def_collector.def_map.modules[self.module_id]
2102 .scope
2103 .define_impl(impl_id, imp.is_trait_impl)
2104 }
2105 ModItemKind::Function(ast_id, it) => {
2106 let fn_id =
2107 FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), ast_id) }
2108 .intern(db);
2109
2110 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2111
2112 update_def(self.def_collector, fn_id.into(), &it.name, vis, None);
2113
2114 if self.def_collector.def_map.block.is_none()
2115 && self.def_collector.is_proc_macro
2116 && self.module_id == self.def_collector.def_map.root
2117 && let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name)
2118 {
2119 self.def_collector.export_proc_macro(
2120 proc_macro,
2121 InFile::new(self.file_id(), ast_id),
2122 fn_id,
2123 );
2124
2125 self.def_collector.def_map[module_id]
2129 .scope
2130 .remove_from_value_ns(&it.name, fn_id.into());
2131 }
2132 }
2133 ModItemKind::Struct(ast_id, it) => {
2134 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2135 let value_ns_ctor_vis = match &it.value_ns_ctor {
2136 StructValueNsCtor::NoValueNsCtor => None,
2137 StructValueNsCtor::ValueNsCtorWithVis(vis) => {
2138 Some(resolve_vis(def_map, local_def_map, &self.item_tree[*vis]))
2139 }
2140 StructValueNsCtor::ValueNsCtorWithMinVis(multiple) => multiple
2141 .iter()
2142 .map(|&vis| resolve_vis(def_map, local_def_map, &self.item_tree[vis]))
2143 .fold(None, |a: Option<Visibility>, b| a?.min(db, b, def_map)),
2144 };
2145 let interned = StructLoc {
2146 container: module_id,
2147 id: InFile::new(self.tree_id.file_id(), ast_id),
2148 }
2149 .intern(db);
2150 consider_deferred_derives(
2151 self.tree_id.file_id(),
2152 &mut self.def_collector.deferred_builtin_derives,
2153 ast_id.upcast(),
2154 interned.into(),
2155 def_map,
2156 );
2157 update_def(
2158 self.def_collector,
2159 interned.into(),
2160 &it.name,
2161 vis,
2162 value_ns_ctor_vis,
2163 );
2164 }
2165 ModItemKind::Union(ast_id, it) => {
2166 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2167 let interned = UnionLoc {
2168 container: module_id,
2169 id: InFile::new(self.tree_id.file_id(), ast_id),
2170 }
2171 .intern(db);
2172 consider_deferred_derives(
2173 self.tree_id.file_id(),
2174 &mut self.def_collector.deferred_builtin_derives,
2175 ast_id.upcast(),
2176 interned.into(),
2177 def_map,
2178 );
2179 update_def(self.def_collector, interned.into(), &it.name, vis, None);
2180 }
2181 ModItemKind::Enum(ast_id, it) => {
2182 let enum_ = EnumLoc {
2183 container: module_id,
2184 id: InFile::new(self.tree_id.file_id(), ast_id),
2185 }
2186 .intern(db);
2187
2188 consider_deferred_derives(
2189 self.tree_id.file_id(),
2190 &mut self.def_collector.deferred_builtin_derives,
2191 ast_id.upcast(),
2192 enum_.into(),
2193 def_map,
2194 );
2195 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2196 update_def(self.def_collector, enum_.into(), &it.name, vis, None);
2197 }
2198 ModItemKind::Const(ast_id, it) => {
2199 let const_id =
2200 ConstLoc { container, id: InFile::new(self.tree_id.file_id(), ast_id) }
2201 .intern(db);
2202
2203 match &it.name {
2204 Some(name) => {
2205 let vis =
2206 resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2207 update_def(self.def_collector, const_id.into(), name, vis, None);
2208 }
2209 None => {
2210 self.def_collector.def_map.modules[self.module_id]
2212 .scope
2213 .define_unnamed_const(const_id);
2214 }
2215 }
2216 }
2217 ModItemKind::Static(ast_id, it) => {
2218 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2219 update_def(
2220 self.def_collector,
2221 StaticLoc { container, id: InFile::new(self.file_id(), ast_id) }
2222 .intern(db)
2223 .into(),
2224 &it.name,
2225 vis,
2226 None,
2227 );
2228 }
2229 ModItemKind::Trait(ast_id, it) => {
2230 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2231 update_def(
2232 self.def_collector,
2233 TraitLoc { container: module_id, id: InFile::new(self.file_id(), ast_id) }
2234 .intern(db)
2235 .into(),
2236 &it.name,
2237 vis,
2238 None,
2239 );
2240 }
2241 ModItemKind::TypeAlias(ast_id, it) => {
2242 let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
2243 update_def(
2244 self.def_collector,
2245 TypeAliasLoc { container, id: InFile::new(self.file_id(), ast_id) }
2246 .intern(db)
2247 .into(),
2248 &it.name,
2249 vis,
2250 None,
2251 );
2252 }
2253 }
2254 };
2255
2256 if is_crate_root {
2260 items
2261 .iter()
2262 .filter(move |&&it| matches!(item_tree.index(it), ModItemKind::ExternCrate(..)))
2263 .copied()
2264 .for_each(&mut process_mod_item);
2265 items
2266 .iter()
2267 .filter(move |&&it| !matches!(item_tree.index(it), ModItemKind::ExternCrate(..)))
2268 .copied()
2269 .for_each(process_mod_item);
2270 } else {
2271 items.iter().copied().for_each(process_mod_item);
2272 }
2273 }
2274
2275 fn process_macro_use_extern_crate<'a>(
2276 &mut self,
2277 extern_crate_id: ExternCrateId,
2278 macro_use_attrs: impl Iterator<Item = &'a Attr>,
2279 target_crate: Crate,
2280 ) {
2281 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
2282 let mut single_imports = Vec::new();
2283 for attr in macro_use_attrs {
2284 let Some(paths) = attr.parse_path_comma_token_tree(self.def_collector.db) else {
2285 self.def_collector.import_macros_from_extern_crate(
2288 target_crate,
2289 None,
2290 Some(extern_crate_id),
2291 );
2292 return;
2293 };
2294 for (path, _, _) in paths {
2295 if let Some(name) = path.as_ident() {
2296 single_imports.push(name.clone());
2297 }
2298 }
2299 }
2300
2301 self.def_collector.import_macros_from_extern_crate(
2302 target_crate,
2303 Some(single_imports),
2304 Some(extern_crate_id),
2305 );
2306 }
2307
2308 fn collect_module(
2309 &mut self,
2310 module_ast_id: ItemTreeAstId<Mod>,
2311 module: &Mod,
2312 attrs: Attrs<'_>,
2313 ) {
2314 let path_attr = attrs.by_key(sym::path).string_value_unescape();
2315 let is_macro_use = attrs.by_key(sym::macro_use).exists();
2316 match &module.kind {
2317 ModKind::Inline { items } => {
2319 let module_id = self.push_child_module(
2320 module.name.clone(),
2321 module_ast_id,
2322 None,
2323 &self.item_tree[module.visibility],
2324 );
2325
2326 let Some(mod_dir) =
2327 self.mod_dir.descend_into_definition(&module.name, path_attr.as_deref())
2328 else {
2329 return;
2330 };
2331 ModCollector {
2332 def_collector: &mut *self.def_collector,
2333 macro_depth: self.macro_depth,
2334 module_id,
2335 tree_id: self.tree_id,
2336 item_tree: self.item_tree,
2337 mod_dir,
2338 }
2339 .collect_in_top_module(items);
2340 if is_macro_use {
2341 self.import_all_legacy_macros(module_id);
2342 }
2343 }
2344 ModKind::Outline => {
2346 let ast_id = AstId::new(self.file_id(), module_ast_id);
2347 let db = self.def_collector.db;
2348 match self.mod_dir.resolve_declaration(
2349 db,
2350 self.file_id(),
2351 &module.name,
2352 path_attr.as_deref(),
2353 ) {
2354 Ok((file_id, is_mod_rs, mod_dir)) => {
2355 let item_tree =
2356 file_item_tree(db, file_id.into(), self.def_collector.def_map.krate);
2357 let top_level_attrs = item_tree.top_level_attrs();
2358 match top_level_attrs {
2359 Some(AttrsOrCfg::CfgDisabled(cfg)) => {
2360 self.emit_unconfigured_diagnostic(
2361 InFile::new(self.file_id(), module_ast_id.erase()),
2362 &cfg.0,
2363 );
2364 }
2365 Some(AttrsOrCfg::Enabled { .. }) | None => {
2366 let module_id = self.push_child_module(
2367 module.name.clone(),
2368 ast_id.value,
2369 Some((file_id, is_mod_rs)),
2370 &self.item_tree[module.visibility],
2371 );
2372 ModCollector {
2373 def_collector: self.def_collector,
2374 macro_depth: self.macro_depth,
2375 module_id,
2376 tree_id: TreeId::new(file_id.into(), None),
2377 item_tree,
2378 mod_dir,
2379 }
2380 .collect_in_top_module(item_tree.top_level_items());
2381 let is_macro_use = is_macro_use
2382 || matches!(top_level_attrs, Some(AttrsOrCfg::Enabled { attrs }) if attrs.as_ref().by_key(sym::macro_use).exists());
2383 if is_macro_use {
2384 self.import_all_legacy_macros(module_id);
2385 }
2386 }
2387 }
2388 }
2389 Err(candidates) => {
2390 self.push_child_module(
2391 module.name.clone(),
2392 ast_id.value,
2393 None,
2394 &self.item_tree[module.visibility],
2395 );
2396 self.def_collector.def_map.diagnostics.push(
2397 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
2398 );
2399 }
2400 };
2401 }
2402 }
2403 }
2404
2405 fn push_child_module(
2406 &mut self,
2407 name: Name,
2408 declaration: FileAstId<ast::Module>,
2409 definition: Option<(EditionedFileId, bool)>,
2410 visibility: &crate::visibility::RawVisibility,
2411 ) -> ModuleId {
2412 let vis = self
2413 .def_collector
2414 .def_map
2415 .resolve_visibility(
2416 self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map),
2417 self.def_collector.db,
2418 self.module_id,
2419 visibility,
2420 false,
2421 )
2422 .unwrap_or(Visibility::Public);
2423 let origin = match definition {
2424 None => {
2425 ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id }
2426 }
2427 Some((definition, is_mod_rs)) => ModuleOrigin::File {
2428 declaration,
2429 definition,
2430 is_mod_rs,
2431 declaration_tree_id: self.tree_id,
2432 },
2433 };
2434
2435 let module = unsafe {
2436 crate::ModuleIdLt::new(
2437 self.def_collector.db,
2438 self.def_collector.def_map.krate,
2439 self.def_collector.def_map.block_id(),
2440 Some(self.module_id),
2441 name.clone(),
2442 )
2443 .to_static()
2444 };
2445 let def_map = &mut self.def_collector.def_map;
2446 let modules = &mut def_map.modules;
2447 let mut data = ModuleData::new(origin, vis, Some(self.module_id));
2448 for (name, macs) in modules[self.module_id].scope.legacy_macros() {
2449 for &mac in macs {
2450 data.scope.define_legacy_macro(name.clone(), mac);
2451 }
2452 }
2453 modules[self.module_id].children.insert(name.clone(), module);
2454 modules.insert(module, data);
2455
2456 let def = ModuleDefId::from(module);
2457
2458 def_map.modules[self.module_id].scope.declare(def);
2459 self.def_collector.update(
2460 self.module_id,
2461 &[(Some(name), PerNs::from_def(def, vis, None, None))],
2462 vis,
2463 None,
2464 );
2465 module
2466 }
2467
2468 fn resolve_attributes(
2476 &mut self,
2477 attrs: Attrs<'_>,
2478 mod_item: ModItemId,
2479 container: ItemContainerId,
2480 ) -> Result<(), ()> {
2481 let ignore_up_to =
2482 self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
2483 for (attr_id, attr) in attrs.iter_after(ignore_up_to) {
2484 if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
2485 continue;
2486 }
2487 tracing::debug!(
2488 "non-builtin attribute {}",
2489 attr.path.display(self.def_collector.db, Edition::LATEST)
2490 );
2491
2492 let ast_id = AstIdWithPath::new(
2493 self.file_id(),
2494 mod_item.ast_id(self.item_tree),
2495 attr.path.clone(),
2496 );
2497 self.def_collector.unresolved_macros.push(MacroDirective {
2498 module_id: self.module_id,
2499 depth: self.macro_depth + 1,
2500 kind: MacroDirectiveKind::Attr {
2501 ast_id,
2502 attr_id,
2503 attr: attr.clone(),
2504 mod_item,
2505 tree: self.tree_id,
2506 item_tree: self.item_tree,
2507 },
2508 container,
2509 });
2510
2511 return Err(());
2512 }
2513
2514 Ok(())
2515 }
2516
2517 fn collect_macro_rules(
2518 &mut self,
2519 attrs: Attrs<'_>,
2520 ast_id: ItemTreeAstId<MacroRules>,
2521 mac: &MacroRules,
2522 module: ModuleId,
2523 ) {
2524 let krate = self.def_collector.def_map.krate;
2525 let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2526
2527 let export_attr = || attrs.by_key(sym::macro_export);
2528
2529 let is_export = export_attr().exists();
2530 let local_inner = if is_export {
2531 export_attr().tt_values().flat_map(|it| it.iter()).any(|it| match it {
2532 tt::TtElement::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros,
2533 _ => false,
2534 })
2535 } else {
2536 false
2537 };
2538
2539 let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2541 let name = match attrs.by_key(sym::rustc_builtin_macro).string_value_with_span() {
2543 Some((it, span)) => &Name::new_symbol(Symbol::intern(it), span.ctx),
2544 None => {
2545 let explicit_name =
2546 attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
2547 match tt.token_trees().iter().next() {
2548 Some(tt::TtElement::Leaf(tt::Leaf::Ident(name))) => Some(name),
2549 _ => None,
2550 }
2551 });
2552 match explicit_name {
2553 Some(ident) => &ident.as_name(),
2554 None => &mac.name,
2555 }
2556 }
2557 };
2558 match find_builtin_macro(name) {
2559 Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
2560 Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
2561 None => {
2562 self.def_collector
2563 .def_map
2564 .diagnostics
2565 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2566 MacroExpander::UnimplementedBuiltIn
2567 }
2568 }
2569 } else {
2570 let id = InFile::new(self.file_id(), ast_id);
2572 let decl_expander = id.upcast().decl_macro_expander(self.def_collector.db, krate);
2573 let styles = decl_expander.mac.rule_styles();
2574 MacroExpander::Declarative { styles }
2575 };
2576 let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2577
2578 let mut flags = MacroRulesLocFlags::empty();
2579 flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
2580 flags.set(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE, allow_internal_unsafe);
2581
2582 let macro_id = MacroRulesLoc {
2583 container: module,
2584 id: InFile::new(self.file_id(), ast_id),
2585 flags,
2586 expander,
2587 edition: self.def_collector.def_map.data.edition,
2588 }
2589 .intern(self.def_collector.db);
2590 self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2591 self.def_collector.define_macro_rules(
2592 self.module_id,
2593 mac.name.clone(),
2594 macro_id,
2595 is_export,
2596 );
2597 }
2598
2599 fn collect_macro_def(
2600 &mut self,
2601 attrs: Attrs<'_>,
2602 ast_id: ItemTreeAstId<Macro2>,
2603 mac: &Macro2,
2604 module: ModuleId,
2605 ) {
2606 let krate = self.def_collector.def_map.krate;
2607 let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
2608
2609 let mut helpers_opt = None;
2611 let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
2612 if let Some(expander) = find_builtin_macro(&mac.name) {
2613 match expander {
2614 Either::Left(it) => MacroExpander::BuiltIn(it),
2615 Either::Right(it) => MacroExpander::BuiltInEager(it),
2616 }
2617 } else if let Some(expander) = find_builtin_derive(&mac.name) {
2618 if let Some(attr) = attrs.by_key(sym::rustc_builtin_macro).tt_values().next() {
2619 if let Some((name, helpers)) = parse_macro_name_and_helper_attrs(attr) {
2623 stdx::always!(
2627 name == mac.name,
2628 "built-in macro {} has #[rustc_builtin_macro] which declares different name {}",
2629 mac.name.display(self.def_collector.db, Edition::LATEST),
2630 name.display(self.def_collector.db, Edition::LATEST),
2631 );
2632 helpers_opt = Some(helpers);
2633 }
2634 }
2635 MacroExpander::BuiltInDerive(expander)
2636 } else if let Some(expander) = find_builtin_attr(&mac.name) {
2637 MacroExpander::BuiltInAttr(expander)
2638 } else {
2639 self.def_collector
2640 .def_map
2641 .diagnostics
2642 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
2643 MacroExpander::UnimplementedBuiltIn
2644 }
2645 } else {
2646 let id = InFile::new(self.file_id(), ast_id);
2648 let decl_expander = id.upcast().decl_macro_expander(self.def_collector.db, krate);
2649 let styles = decl_expander.mac.rule_styles();
2650 MacroExpander::Declarative { styles }
2651 };
2652 let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
2653
2654 let macro_id = Macro2Loc {
2655 container: module,
2656 id: InFile::new(self.file_id(), ast_id),
2657 expander,
2658 allow_internal_unsafe,
2659 edition: self.def_collector.def_map.data.edition,
2660 }
2661 .intern(self.def_collector.db);
2662 self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
2663 self.def_collector.define_macro_def(
2664 self.module_id,
2665 mac.name.clone(),
2666 macro_id,
2667 &self.item_tree[mac.visibility],
2668 );
2669 if let Some(helpers) = helpers_opt
2670 && self.def_collector.def_map.block.is_none()
2671 {
2672 Arc::get_mut(&mut self.def_collector.def_map.data)
2673 .unwrap()
2674 .exported_derives
2675 .insert(macro_id.into(), helpers);
2676 }
2677 }
2678
2679 fn collect_macro_call(
2680 &mut self,
2681 ast_id: FileAstId<ast::MacroCall>,
2682 macro_call: &MacroCall,
2683 container: ItemContainerId,
2684 ) {
2685 let &MacroCall { ref path, expand_to, ctxt } = macro_call;
2686 let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone());
2687 let db = self.def_collector.db;
2688
2689 let mut eager_callback_buffer = vec![];
2694 if let Ok(res) = macro_call_as_call_id(
2696 db,
2697 ast_id.ast_id,
2698 &ast_id.path,
2699 ctxt,
2700 expand_to,
2701 self.def_collector.def_map.krate,
2702 self.macro_depth + 1,
2703 self.def_collector.def_map.recursion_limit(),
2704 |path| {
2705 path.as_ident().and_then(|name| {
2706 let def_map = &self.def_collector.def_map;
2707 def_map
2708 .with_ancestor_maps(db, self.module_id, &mut |map, module| {
2709 map[module].scope.get_legacy_macro(name)?.last().copied()
2710 })
2711 .or_else(|| def_map[self.module_id].scope.get(name).take_macros())
2712 .or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0))
2713 .filter(|&id| sub_namespace_match(db, id, Some(MacroSubNs::Bang)))
2714 .map(|it| it.definition(self.def_collector.db))
2715 })
2716 },
2717 &mut |ptr, call_id| eager_callback_buffer.push((ptr, call_id)),
2718 ) {
2719 for (ptr, call_id) in eager_callback_buffer {
2720 self.def_collector.def_map.modules[self.module_id]
2721 .scope
2722 .add_macro_invoc(ptr.map(|(_, it)| it), call_id);
2723 }
2724 if res.err.is_none() {
2727 if let Some(call_id) = res.value {
2730 self.def_collector.def_map.modules[self.module_id]
2731 .scope
2732 .add_macro_invoc(ast_id.ast_id, call_id);
2733 self.def_collector.collect_macro_expansion(
2734 self.module_id,
2735 call_id,
2736 self.macro_depth + 1,
2737 container,
2738 None,
2739 );
2740 }
2741
2742 return;
2743 }
2744 }
2745
2746 self.def_collector.unresolved_macros.push(MacroDirective {
2748 module_id: self.module_id,
2749 depth: self.macro_depth + 1,
2750 kind: MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt },
2751 container,
2752 });
2753 }
2754
2755 fn import_all_legacy_macros(&mut self, module_id: ModuleId) {
2756 let [Some(source), Some(target)] =
2757 self.def_collector.def_map.modules.get_disjoint_mut([&module_id, &self.module_id])
2758 else {
2759 return;
2760 };
2761
2762 for (name, macs) in source.scope.legacy_macros() {
2763 if let Some(&mac) = macs.last() {
2764 target.scope.define_legacy_macro(name.clone(), mac);
2765 }
2766 }
2767 }
2768
2769 fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedAstId, cfg: &CfgExpr) {
2770 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2771 self.module_id,
2772 ast_id,
2773 cfg.clone(),
2774 self.def_collector.cfg_options.clone(),
2775 ));
2776 }
2777
2778 #[inline]
2779 fn file_id(&self) -> HirFileId {
2780 self.tree_id.file_id()
2781 }
2782}
2783
2784#[cfg(test)]
2785mod tests {
2786 use test_fixture::WithFixture;
2787
2788 use crate::test_db::TestDB;
2789
2790 use super::*;
2791
2792 fn do_resolve(not_ra_fixture: &str) {
2793 let (db, _) = TestDB::with_single_file(not_ra_fixture);
2794 let krate = db.test_crate();
2795
2796 crate_def_map(&db, krate);
2797 }
2798
2799 #[test]
2800 fn test_macro_expand_will_stop_1() {
2801 do_resolve(
2802 r#"
2803macro_rules! foo {
2804 ($($ty:ty)*) => { foo!($($ty)*); }
2805}
2806foo!(KABOOM);
2807"#,
2808 );
2809 do_resolve(
2810 r#"
2811macro_rules! foo {
2812 ($($ty:ty)*) => { foo!(() $($ty)*); }
2813}
2814foo!(KABOOM);
2815"#,
2816 );
2817 }
2818
2819 #[ignore]
2820 #[test]
2821 fn test_macro_expand_will_stop_2() {
2822 do_resolve(
2828 r#"
2829macro_rules! foo {
2830 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2831}
2832foo!(KABOOM);
2833"#,
2834 );
2835 }
2836
2837 #[test]
2838 fn crate_attrs() {
2839 let fixture = r#"
2840//- /lib.rs crate:foo crate-attr:recursion_limit="4" crate-attr:no_core crate-attr:no_std crate-attr:feature(register_tool)
2841 "#;
2842 let (db, _) = TestDB::with_single_file(fixture);
2843 let def_map = crate_def_map(&db, db.test_crate());
2844 assert_eq!(def_map.recursion_limit(), 4);
2845 assert!(def_map.is_no_core());
2846 assert!(def_map.is_no_std());
2847 assert!(def_map.features().is_enabled(&sym::register_tool));
2848 }
2849}