1pub mod assoc;
51pub mod attr_resolution;
52mod collector;
53pub mod diagnostics;
54mod mod_resolution;
55mod path_resolution;
56pub mod proc_macro;
57
58#[cfg(test)]
59mod tests;
60
61use std::ops::{Deref, DerefMut, Index, IndexMut};
62
63use base_db::{Crate, SourceDatabase};
64use either::Either;
65use hir_expand::{
66 EditionedFileId, ErasedAstId, HirFileId, InFile, MacroCallId, mod_path::ModPath, name::Name,
67 proc_macro::ProcMacroKind,
68};
69use intern::{Symbol, sym};
70use itertools::Itertools;
71use rustc_hash::FxHashMap;
72use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
73use stdx::format_to;
74use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast};
75use triomphe::Arc;
76use tt::TextRange;
77
78use crate::{
79 AstId, BlockId, BlockIdLt, BuiltinDeriveImplId, ExternCrateId, FunctionId, FxIndexMap, Lookup,
80 MacroCallStyles, MacroExpander, MacroId, ModuleId, ModuleIdLt, ProcMacroId, UseId,
81 item_scope::{BuiltinShadowMode, ItemScope},
82 item_tree::TreeId,
83 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
84 per_ns::PerNs,
85 unstable_features::UnstableFeatures,
86 visibility::{Visibility, VisibilityExplicitness},
87};
88
89pub use self::path_resolution::ResolvePathResultPrefixInfo;
90
91#[cfg(test)]
92thread_local! {
93 pub(crate) static ENABLE_BUILTIN_DERIVE_FAST_PATH: std::cell::Cell<bool> =
95 const { std::cell::Cell::new(true) };
96}
97
98#[inline]
99#[cfg(test)]
100fn enable_builtin_derive_fast_path() -> bool {
101 ENABLE_BUILTIN_DERIVE_FAST_PATH.get()
102}
103
104#[inline(always)]
105#[cfg(not(test))]
106fn enable_builtin_derive_fast_path() -> bool {
107 true
108}
109
110const PREDEFINED_TOOLS: &[SmolStr] = &[
111 SmolStr::new_static("clippy"),
112 SmolStr::new_static("rustfmt"),
113 SmolStr::new_static("diagnostic"),
114 SmolStr::new_static("miri"),
115 SmolStr::new_static("rust_analyzer"),
116];
117
118#[derive(Debug, PartialEq, Eq, Default)]
127pub struct LocalDefMap {
128 extern_prelude: FxIndexMap<Name, (ModuleId, Option<ExternCrateId>)>,
132}
133
134impl std::hash::Hash for LocalDefMap {
135 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
136 let LocalDefMap { extern_prelude } = self;
137 extern_prelude.len().hash(state);
138 for (name, (crate_root, extern_crate)) in extern_prelude {
139 name.hash(state);
140 crate_root.hash(state);
141 extern_crate.hash(state);
142 }
143 }
144}
145
146impl LocalDefMap {
147 pub(crate) const EMPTY: &Self =
148 &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) };
149
150 fn shrink_to_fit(&mut self) {
151 let Self { extern_prelude } = self;
152 extern_prelude.shrink_to_fit();
153 }
154
155 pub(crate) fn extern_prelude(
156 &self,
157 ) -> impl DoubleEndedIterator<Item = (&Name, (ModuleId, Option<ExternCrateId>))> + '_ {
158 self.extern_prelude.iter().map(|(name, &def)| (name, def))
159 }
160}
161
162#[derive(Debug, PartialEq, Eq)]
172pub struct DefMap {
173 krate: Crate,
175 block: Option<BlockInfo>,
178 pub root: ModuleId,
179 pub modules: ModulesMap,
181 prelude: Option<(ModuleId, Option<UseId>)>,
188 macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
192
193 derive_helpers_in_scope:
197 FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, Either<MacroCallId, BuiltinDeriveImplId>)>>,
198 pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>,
200
201 diagnostics: Vec<DefDiagnostic>,
203
204 data: Arc<DefMapCrateData>,
206}
207
208#[derive(Clone, Debug, PartialEq, Eq)]
210struct DefMapCrateData {
211 exported_derives: FxHashMap<MacroId, Box<[Name]>>,
213 fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
214 fn_proc_macro_mapping_back: FxHashMap<ProcMacroId, FunctionId>,
215
216 registered_tools: Vec<Symbol>,
218 unstable_features: UnstableFeatures,
220 rustc_coherence_is_core: bool,
222 no_core: bool,
223 no_std: bool,
224
225 edition: Edition,
226 recursion_limit: Option<u32>,
227}
228
229impl DefMapCrateData {
230 fn new(edition: Edition) -> Self {
231 Self {
232 exported_derives: FxHashMap::default(),
233 fn_proc_macro_mapping: FxHashMap::default(),
234 fn_proc_macro_mapping_back: FxHashMap::default(),
235 registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
236 unstable_features: UnstableFeatures::default(),
237 rustc_coherence_is_core: false,
238 no_core: false,
239 no_std: false,
240 edition,
241 recursion_limit: None,
242 }
243 }
244
245 fn shrink_to_fit(&mut self) {
246 let Self {
247 exported_derives,
248 fn_proc_macro_mapping,
249 fn_proc_macro_mapping_back,
250 registered_tools,
251 unstable_features,
252 rustc_coherence_is_core: _,
253 no_core: _,
254 no_std: _,
255 edition: _,
256 recursion_limit: _,
257 } = self;
258 exported_derives.shrink_to_fit();
259 fn_proc_macro_mapping.shrink_to_fit();
260 fn_proc_macro_mapping_back.shrink_to_fit();
261 registered_tools.shrink_to_fit();
262 unstable_features.shrink_to_fit();
263 }
264}
265
266#[derive(Debug, PartialEq, Eq, Clone, Copy)]
268struct BlockInfo {
269 block: BlockId,
271 parent: ModuleId,
273}
274
275impl std::ops::Index<ModuleIdLt<'_>> for DefMap {
276 type Output = ModuleData;
277
278 fn index(&self, id: ModuleIdLt<'_>) -> &ModuleData {
279 self.modules
280 .get(&unsafe { id.to_static() })
281 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap {:#?}: {id:#?}", self.root))
282 }
283}
284
285impl std::ops::IndexMut<ModuleId> for DefMap {
286 fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
287 &mut self.modules[id]
288 }
289}
290
291#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
292pub enum ModuleOrigin {
293 CrateRoot {
294 definition: EditionedFileId,
295 },
296 File {
298 is_mod_rs: bool,
299 declaration: FileAstId<ast::Module>,
300 declaration_tree_id: TreeId,
301 definition: EditionedFileId,
302 },
303 Inline {
304 definition_tree_id: TreeId,
305 definition: FileAstId<ast::Module>,
306 },
307 BlockExpr {
309 id: BlockId,
310 block: AstId<ast::BlockExpr>,
311 },
312}
313
314impl ModuleOrigin {
315 pub fn declaration(&self) -> Option<AstId<ast::Module>> {
316 match self {
317 &ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
318 Some(AstId::new(declaration_tree_id.file_id(), declaration))
319 }
320 &ModuleOrigin::Inline { definition, definition_tree_id } => {
321 Some(AstId::new(definition_tree_id.file_id(), definition))
322 }
323 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
324 }
325 }
326
327 pub fn file_id(&self) -> Option<EditionedFileId> {
328 match self {
329 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
330 Some(*definition)
331 }
332 _ => None,
333 }
334 }
335
336 pub fn is_inline(&self) -> bool {
337 match self {
338 ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
339 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
340 }
341 }
342
343 pub fn definition_source(&self, db: &dyn SourceDatabase) -> InFile<ModuleSource> {
346 match self {
347 &ModuleOrigin::File { definition: editioned_file_id, .. }
348 | &ModuleOrigin::CrateRoot { definition: editioned_file_id } => {
349 let sf = editioned_file_id.parse(db).tree();
350 InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf))
351 }
352 &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
353 definition_tree_id.file_id(),
354 ModuleSource::Module(
355 AstId::new(definition_tree_id.file_id(), definition).to_node(db),
356 ),
357 ),
358 ModuleOrigin::BlockExpr { block, .. } => {
359 InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db)))
360 }
361 }
362 }
363}
364
365#[derive(Debug, PartialEq, Eq)]
366pub struct ModuleData {
367 pub origin: ModuleOrigin,
369 pub visibility: Visibility,
371 pub parent: Option<ModuleId>,
375 pub children: FxIndexMap<Name, ModuleId>,
376 pub scope: ItemScope,
377}
378
379#[inline]
380pub fn crate_def_map(db: &dyn SourceDatabase, crate_id: Crate) -> &DefMap {
381 crate_local_def_map(db, crate_id).def_map(db)
382}
383
384#[salsa::tracked]
385pub(crate) struct DefMapPair<'db> {
386 #[tracked]
387 #[returns(ref)]
388 pub(crate) def_map: DefMap,
389 #[returns(ref)]
390 pub(crate) local: LocalDefMap,
391}
392
393#[salsa::tracked(returns(ref))]
394pub(crate) fn crate_local_def_map(db: &dyn SourceDatabase, crate_id: Crate) -> DefMapPair<'_> {
395 let krate = crate_id.data(db);
396 let _p = tracing::info_span!(
397 "crate_def_map_query",
398 name=?crate_id
399 .extra_data(db)
400 .display_name
401 .as_ref()
402 .map(|it| it.crate_name().to_smolstr())
403 .unwrap_or_default()
404 )
405 .entered();
406
407 let root_file_id = crate_id.root_file_id(db);
408 let module_data = ModuleData::new(
409 ModuleOrigin::CrateRoot { definition: root_file_id },
410 Visibility::Public,
411 None,
412 );
413
414 let def_map = DefMap::empty(
415 db,
416 crate_id,
417 Arc::new(DefMapCrateData::new(krate.edition)),
418 module_data,
419 None,
420 );
421 let (def_map, local_def_map) =
422 collector::collect_defs(db, def_map, TreeId::new(root_file_id.into(), None), None);
423
424 DefMapPair::new(db, def_map, local_def_map)
425}
426
427#[salsa::tracked(returns(ref))]
428pub fn block_def_map<'db>(db: &'db dyn SourceDatabase, block_id: BlockIdLt<'db>) -> DefMap {
429 let block_id = unsafe { block_id.to_static() };
430 let ast_id = block_id.ast_id(db);
431 let module = unsafe { block_id.module(db).to_static() };
432
433 let visibility = Visibility::Module(module, VisibilityExplicitness::Implicit);
434 let module_data =
435 ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility, None);
436
437 let krate = module.krate(db);
438 let local_def_map = crate_local_def_map(db, krate);
439 let def_map = DefMap::empty(
440 db,
441 krate,
442 local_def_map.def_map(db).data.clone(),
443 module_data,
444 Some(BlockInfo { block: block_id, parent: module }),
445 );
446
447 let (def_map, _) = collector::collect_defs(
448 db,
449 def_map,
450 TreeId::new(ast_id.file_id, Some(block_id)),
451 Some(local_def_map.local(db)),
452 );
453 def_map
454}
455
456impl DefMap {
457 pub fn edition(&self) -> Edition {
458 self.data.edition
459 }
460
461 fn empty(
462 db: &dyn SourceDatabase,
463 krate: Crate,
464 crate_data: Arc<DefMapCrateData>,
465 module_data: ModuleData,
466 block: Option<BlockInfo>,
467 ) -> DefMap {
468 let mut modules = ModulesMap::new();
469 let root = unsafe {
470 ModuleIdLt::new(
471 db,
472 krate,
473 block.map(|it| it.block),
474 None,
475 Name::new_symbol_root(sym::__empty),
476 )
477 .to_static()
478 };
479 modules.insert(root, module_data);
480
481 DefMap {
482 block,
483 root,
484 modules,
485 krate,
486 prelude: None,
487 macro_use_prelude: FxHashMap::default(),
488 derive_helpers_in_scope: FxHashMap::default(),
489 diagnostics: Vec::new(),
490 data: crate_data,
491 macro_def_to_macro_id: FxHashMap::default(),
492 }
493 }
494 fn shrink_to_fit(&mut self) {
495 let Self {
497 macro_use_prelude,
498 diagnostics,
499 modules,
500 derive_helpers_in_scope,
501 root: _,
502 block: _,
503 krate: _,
504 prelude: _,
505 data: _,
506 macro_def_to_macro_id,
507 } = self;
508
509 macro_def_to_macro_id.shrink_to_fit();
510 macro_use_prelude.shrink_to_fit();
511 diagnostics.shrink_to_fit();
512 modules.shrink_to_fit();
513 derive_helpers_in_scope.shrink_to_fit();
514 for (_, module) in modules.iter_mut() {
515 module.children.shrink_to_fit();
516 module.scope.shrink_to_fit();
517 }
518 }
519}
520
521impl DefMap {
522 pub fn modules_for_file<'a>(
524 &'a self,
525 db: &'a dyn SourceDatabase,
526 file_id: FileId,
527 ) -> impl Iterator<Item = ModuleId> + 'a {
528 self.modules
529 .iter()
530 .filter(move |(_, data)| {
531 data.origin.file_id().map(|file_id| file_id.file_id(db)) == Some(file_id)
532 })
533 .map(|(id, _)| id)
534 }
535
536 pub fn modules(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
537 self.modules.iter()
538 }
539
540 pub fn inline_modules_for_macro_file(
542 &self,
543 file_id: MacroCallId,
544 ) -> impl Iterator<Item = ModuleId> + '_ {
545 self.modules
546 .iter()
547 .filter(move |(_, data)| {
548 matches!(
549 data.origin,
550 ModuleOrigin::Inline { definition_tree_id, .. }
551 if definition_tree_id.file_id().macro_file() == Some(file_id)
552 )
553 })
554 .map(|(id, _)| id)
555 }
556
557 pub fn derive_helpers_in_scope(
558 &self,
559 id: AstId<ast::Adt>,
560 ) -> Option<&[(Name, MacroId, Either<MacroCallId, BuiltinDeriveImplId>)]> {
561 self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref)
562 }
563
564 pub fn registered_tools(&self) -> &[Symbol] {
565 &self.data.registered_tools
566 }
567
568 #[inline]
569 pub fn features(&self) -> &UnstableFeatures {
570 &self.data.unstable_features
571 }
572
573 pub fn is_rustc_coherence_is_core(&self) -> bool {
574 self.data.rustc_coherence_is_core
575 }
576
577 pub fn is_no_std(&self) -> bool {
578 self.data.no_std || self.data.no_core
579 }
580
581 pub fn is_no_core(&self) -> bool {
582 self.data.no_core
583 }
584
585 pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
586 self.data.fn_proc_macro_mapping.get(&id).copied()
587 }
588
589 pub fn proc_macro_as_fn(&self, id: ProcMacroId) -> Option<FunctionId> {
590 self.data.fn_proc_macro_mapping_back.get(&id).copied()
591 }
592
593 pub fn krate(&self) -> Crate {
594 self.krate
595 }
596
597 #[inline]
598 pub fn crate_root(&self, db: &dyn SourceDatabase) -> ModuleId {
599 match self.block {
600 Some(_) => crate_def_map(db, self.krate()).root,
601 None => self.root,
602 }
603 }
604
605 pub fn root_module_id(&self) -> ModuleId {
608 self.root
609 }
610
611 pub fn parent(&self) -> Option<ModuleId> {
614 Some(self.block?.parent)
615 }
616
617 pub fn containing_module(&self, local_mod: ModuleIdLt<'_>) -> Option<ModuleId> {
620 match self[local_mod].parent {
621 Some(parent) => Some(parent),
622 None => self.block.map(|BlockInfo { parent, .. }| parent),
623 }
624 }
625
626 pub fn diagnostics(&self) -> &[DefDiagnostic] {
628 self.diagnostics.as_slice()
629 }
630
631 pub fn recursion_limit(&self) -> u32 {
632 self.data.recursion_limit.unwrap_or(128)
634 }
635
636 pub fn dump(&self, db: &dyn SourceDatabase) -> String {
639 let mut buf = String::new();
640 let mut current_map = self;
641 while let Some(block) = current_map.block {
642 go(&mut buf, db, current_map, "(block scope)", current_map.root);
643 buf.push('\n');
644 current_map = block.parent.def_map(db);
645 }
646 go(&mut buf, db, current_map, "crate", current_map.root);
647 return buf;
648
649 fn go(
650 buf: &mut String,
651 db: &dyn SourceDatabase,
652 map: &DefMap,
653 path: &str,
654 module: ModuleId,
655 ) {
656 format_to!(buf, "{}\n", path);
657
658 map[module].scope.dump(db, buf);
659
660 for (name, child) in map[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
661 {
662 let path = format!("{path}::{}", name.display(db, Edition::LATEST));
663 buf.push('\n');
664 go(buf, db, map, &path, *child);
665 }
666 }
667 }
668}
669
670impl DefMap {
671 pub(crate) fn block_id(&self) -> Option<BlockId> {
672 self.block.map(|block| block.block)
673 }
674
675 pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
676 self.prelude
677 }
678
679 pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
680 &self.macro_use_prelude
681 }
682
683 pub(crate) fn resolve_path(
684 &self,
685 local_def_map: &LocalDefMap,
686 db: &dyn SourceDatabase,
687 original_module: ModuleId,
688 path: &ModPath,
689 shadow: BuiltinShadowMode,
690 expected_macro_subns: Option<MacroSubNs>,
691 ) -> (PerNs, Option<usize>) {
692 let res = self.resolve_path_fp_with_macro(
693 local_def_map,
694 db,
695 ResolveMode::Other,
696 original_module,
697 path,
698 shadow,
699 expected_macro_subns,
700 );
701 (res.resolved_def, res.segment_index)
702 }
703
704 pub(crate) fn resolve_path_locally(
707 &self,
708 local_def_map: &LocalDefMap,
709 db: &dyn SourceDatabase,
710 original_module: ModuleId,
711 path: &ModPath,
712 shadow: BuiltinShadowMode,
713 ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
714 let res = self.resolve_path_fp_with_macro_single(
715 local_def_map,
716 db,
717 ResolveMode::Other,
718 original_module,
719 path,
720 shadow,
721 None, );
723 (res.resolved_def, res.segment_index, res.prefix_info)
724 }
725
726 pub(crate) fn with_ancestor_maps<'db, T>(
731 &self,
732 db: &'db dyn SourceDatabase,
733 local_mod: ModuleIdLt<'db>,
734 f: &mut dyn FnMut(&DefMap, ModuleIdLt<'db>) -> Option<T>,
735 ) -> Option<T> {
736 if let Some(it) = f(self, local_mod) {
737 return Some(it);
738 }
739 let mut block = self.block;
740 while let Some(block_info) = block {
741 let parent = block_info.parent.def_map(db);
742 if let Some(it) = f(parent, block_info.parent) {
743 return Some(it);
744 }
745 block = parent.block;
746 }
747
748 None
749 }
750}
751
752impl ModuleData {
753 pub(crate) fn new(
754 origin: ModuleOrigin,
755 visibility: Visibility,
756 parent: Option<ModuleId>,
757 ) -> Self {
758 ModuleData {
759 origin,
760 visibility,
761 parent,
762 children: Default::default(),
763 scope: ItemScope::default(),
764 }
765 }
766
767 pub fn definition_source(&self, db: &dyn SourceDatabase) -> InFile<ModuleSource> {
769 self.origin.definition_source(db)
770 }
771
772 pub fn definition_source_file_id(&self) -> HirFileId {
774 match self.origin {
775 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
776 definition.into()
777 }
778 ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
779 ModuleOrigin::BlockExpr { block, .. } => block.file_id,
780 }
781 }
782
783 pub fn definition_source_range(&self, db: &dyn SourceDatabase) -> InFile<TextRange> {
784 match &self.origin {
785 &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
786 InFile::new(
787 definition.into(),
788 ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db),
789 )
790 }
791 &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
792 definition_tree_id.file_id(),
793 AstId::new(definition_tree_id.file_id(), definition).to_range(db),
794 ),
795 ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)),
796 }
797 }
798
799 pub fn declaration_source(&self, db: &dyn SourceDatabase) -> Option<InFile<ast::Module>> {
802 let decl = self.origin.declaration()?;
803 let value = decl.to_node(db);
804 Some(InFile { file_id: decl.file_id, value })
805 }
806
807 pub fn declaration_source_range(&self, db: &dyn SourceDatabase) -> Option<InFile<TextRange>> {
810 let decl = self.origin.declaration()?;
811 Some(InFile { file_id: decl.file_id, value: decl.to_range(db) })
812 }
813}
814
815#[derive(Debug, Clone, PartialEq, Eq)]
816pub enum ModuleSource {
817 SourceFile(ast::SourceFile),
818 Module(ast::Module),
819 BlockExpr(ast::BlockExpr),
820}
821
822impl ModuleSource {
823 pub fn node(&self) -> SyntaxNode {
824 match self {
825 ModuleSource::SourceFile(it) => it.syntax().clone(),
826 ModuleSource::Module(it) => it.syntax().clone(),
827 ModuleSource::BlockExpr(it) => it.syntax().clone(),
828 }
829 }
830}
831
832#[derive(Clone, Copy, PartialEq, Eq)]
834pub enum MacroSubNs {
835 Bang,
837 Attr,
839}
840
841pub(crate) fn macro_styles_from_id(db: &dyn SourceDatabase, macro_id: MacroId) -> MacroCallStyles {
842 let expander = match macro_id {
843 MacroId::Macro2Id(it) => it.lookup(db).expander,
844 MacroId::MacroRulesId(it) => it.lookup(db).expander,
845 MacroId::ProcMacroId(it) => {
846 return match it.lookup(db).kind {
847 ProcMacroKind::CustomDerive => MacroCallStyles::DERIVE,
848 ProcMacroKind::Bang => MacroCallStyles::FN_LIKE,
849 ProcMacroKind::Attr => MacroCallStyles::ATTR,
850 };
851 }
852 };
853
854 match expander {
855 MacroExpander::Declarative { styles } => styles,
856 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroCallStyles::FN_LIKE,
858 MacroExpander::BuiltInAttr(_) => MacroCallStyles::ATTR,
859 MacroExpander::BuiltInDerive(_) => MacroCallStyles::DERIVE,
860 MacroExpander::UnimplementedBuiltIn => MacroCallStyles::all(), }
862}
863
864fn sub_namespace_match(
871 db: &dyn SourceDatabase,
872 macro_id: MacroId,
873 expected: Option<MacroSubNs>,
874) -> bool {
875 let candidate = macro_styles_from_id(db, macro_id);
876 match expected {
877 Some(MacroSubNs::Bang) => candidate.contains(MacroCallStyles::FN_LIKE),
878 Some(MacroSubNs::Attr) => {
879 candidate.contains(MacroCallStyles::ATTR) || candidate.contains(MacroCallStyles::DERIVE)
880 }
881 None => true,
884 }
885}
886
887#[derive(Debug, PartialEq, Eq)]
889pub struct ModulesMap {
890 inner: FxIndexMap<ModuleId, ModuleData>,
891}
892
893impl ModulesMap {
894 fn new() -> Self {
895 Self { inner: FxIndexMap::default() }
896 }
897
898 fn iter(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
899 self.inner.iter().map(|(&k, v)| (k, v))
900 }
901
902 fn iter_mut(&mut self) -> impl Iterator<Item = (ModuleId, &mut ModuleData)> + '_ {
903 self.inner.iter_mut().map(|(&k, v)| (k, v))
904 }
905}
906
907impl Deref for ModulesMap {
908 type Target = FxIndexMap<ModuleId, ModuleData>;
909
910 fn deref(&self) -> &Self::Target {
911 &self.inner
912 }
913}
914
915impl DerefMut for ModulesMap {
916 fn deref_mut(&mut self) -> &mut Self::Target {
917 &mut self.inner
918 }
919}
920
921impl Index<ModuleIdLt<'_>> for ModulesMap {
922 type Output = ModuleData;
923
924 fn index(&self, id: ModuleIdLt<'_>) -> &ModuleData {
925 self.inner
926 .get(&unsafe { id.to_static() })
927 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
928 }
929}
930
931impl IndexMut<ModuleId> for ModulesMap {
932 fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
933 self.inner
934 .get_mut(&id)
935 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
936 }
937}