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;
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;
70use itertools::Itertools;
71use rustc_hash::{FxHashMap, FxHashSet};
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, BlockLoc, BuiltinDeriveImplId, ExternCrateId, FunctionId, FxIndexMap, Lookup,
80 MacroCallStyles, MacroExpander, MacroId, ModuleId, ModuleIdLt, ProcMacroId, UseId,
81 db::DefDatabase,
82 item_scope::{BuiltinShadowMode, ItemScope},
83 item_tree::TreeId,
84 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
85 per_ns::PerNs,
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: FxHashSet<Symbol>,
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: FxHashSet::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<ModuleId> for DefMap {
276 type Output = ModuleData;
277
278 fn index(&self, id: ModuleId) -> &ModuleData {
279 self.modules
280 .get(&id)
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 DefDatabase) -> 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 DefDatabase, crate_id: Crate) -> &DefMap {
381 crate_local_def_map(db, crate_id).def_map(db)
382}
383
384#[salsa_macros::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_macros::tracked(returns(ref))]
394pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, 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_macros::tracked(returns(ref))]
428pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
429 let BlockLoc { ast_id, module } = block_id.lookup(db);
430
431 let visibility = Visibility::Module(module, VisibilityExplicitness::Implicit);
432 let module_data =
433 ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility, None);
434
435 let krate = module.krate(db);
436 let local_def_map = crate_local_def_map(db, krate);
437 let def_map = DefMap::empty(
438 db,
439 krate,
440 local_def_map.def_map(db).data.clone(),
441 module_data,
442 Some(BlockInfo { block: block_id, parent: module }),
443 );
444
445 let (def_map, _) = collector::collect_defs(
446 db,
447 def_map,
448 TreeId::new(ast_id.file_id, Some(block_id)),
449 Some(local_def_map.local(db)),
450 );
451 def_map
452}
453
454impl DefMap {
455 pub fn edition(&self) -> Edition {
456 self.data.edition
457 }
458
459 fn empty(
460 db: &dyn DefDatabase,
461 krate: Crate,
462 crate_data: Arc<DefMapCrateData>,
463 module_data: ModuleData,
464 block: Option<BlockInfo>,
465 ) -> DefMap {
466 let mut modules = ModulesMap::new();
467 let root = unsafe { ModuleIdLt::new(db, krate, block.map(|it| it.block)).to_static() };
468 modules.insert(root, module_data);
469
470 DefMap {
471 block,
472 root,
473 modules,
474 krate,
475 prelude: None,
476 macro_use_prelude: FxHashMap::default(),
477 derive_helpers_in_scope: FxHashMap::default(),
478 diagnostics: Vec::new(),
479 data: crate_data,
480 macro_def_to_macro_id: FxHashMap::default(),
481 }
482 }
483 fn shrink_to_fit(&mut self) {
484 let Self {
486 macro_use_prelude,
487 diagnostics,
488 modules,
489 derive_helpers_in_scope,
490 root: _,
491 block: _,
492 krate: _,
493 prelude: _,
494 data: _,
495 macro_def_to_macro_id,
496 } = self;
497
498 macro_def_to_macro_id.shrink_to_fit();
499 macro_use_prelude.shrink_to_fit();
500 diagnostics.shrink_to_fit();
501 modules.shrink_to_fit();
502 derive_helpers_in_scope.shrink_to_fit();
503 for (_, module) in modules.iter_mut() {
504 module.children.shrink_to_fit();
505 module.scope.shrink_to_fit();
506 }
507 }
508}
509
510impl DefMap {
511 pub fn modules_for_file<'a>(
513 &'a self,
514 db: &'a dyn DefDatabase,
515 file_id: FileId,
516 ) -> impl Iterator<Item = ModuleId> + 'a {
517 self.modules
518 .iter()
519 .filter(move |(_, data)| {
520 data.origin.file_id().map(|file_id| file_id.file_id(db)) == Some(file_id)
521 })
522 .map(|(id, _)| id)
523 }
524
525 pub fn modules(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
526 self.modules.iter()
527 }
528
529 pub fn inline_modules_for_macro_file(
531 &self,
532 file_id: MacroCallId,
533 ) -> impl Iterator<Item = ModuleId> + '_ {
534 self.modules
535 .iter()
536 .filter(move |(_, data)| {
537 matches!(
538 data.origin,
539 ModuleOrigin::Inline { definition_tree_id, .. }
540 if definition_tree_id.file_id().macro_file() == Some(file_id)
541 )
542 })
543 .map(|(id, _)| id)
544 }
545
546 pub fn derive_helpers_in_scope(
547 &self,
548 id: AstId<ast::Adt>,
549 ) -> Option<&[(Name, MacroId, Either<MacroCallId, BuiltinDeriveImplId>)]> {
550 self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref)
551 }
552
553 pub fn registered_tools(&self) -> &[Symbol] {
554 &self.data.registered_tools
555 }
556
557 pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
558 self.data.unstable_features.contains(feature)
559 }
560
561 pub fn is_rustc_coherence_is_core(&self) -> bool {
562 self.data.rustc_coherence_is_core
563 }
564
565 pub fn is_no_std(&self) -> bool {
566 self.data.no_std || self.data.no_core
567 }
568
569 pub fn is_no_core(&self) -> bool {
570 self.data.no_core
571 }
572
573 pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
574 self.data.fn_proc_macro_mapping.get(&id).copied()
575 }
576
577 pub fn proc_macro_as_fn(&self, id: ProcMacroId) -> Option<FunctionId> {
578 self.data.fn_proc_macro_mapping_back.get(&id).copied()
579 }
580
581 pub fn krate(&self) -> Crate {
582 self.krate
583 }
584
585 #[inline]
586 pub fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId {
587 match self.block {
588 Some(_) => crate_def_map(db, self.krate()).root,
589 None => self.root,
590 }
591 }
592
593 pub fn root_module_id(&self) -> ModuleId {
596 self.root
597 }
598
599 pub fn parent(&self) -> Option<ModuleId> {
602 Some(self.block?.parent)
603 }
604
605 pub fn containing_module(&self, local_mod: ModuleId) -> Option<ModuleId> {
608 match self[local_mod].parent {
609 Some(parent) => Some(parent),
610 None => self.block.map(|BlockInfo { parent, .. }| parent),
611 }
612 }
613
614 pub fn diagnostics(&self) -> &[DefDiagnostic] {
616 self.diagnostics.as_slice()
617 }
618
619 pub fn recursion_limit(&self) -> u32 {
620 self.data.recursion_limit.unwrap_or(128)
622 }
623
624 pub fn dump(&self, db: &dyn DefDatabase) -> String {
627 let mut buf = String::new();
628 let mut current_map = self;
629 while let Some(block) = current_map.block {
630 go(&mut buf, db, current_map, "(block scope)", current_map.root);
631 buf.push('\n');
632 current_map = block.parent.def_map(db);
633 }
634 go(&mut buf, db, current_map, "crate", current_map.root);
635 return buf;
636
637 fn go(buf: &mut String, db: &dyn DefDatabase, map: &DefMap, path: &str, module: ModuleId) {
638 format_to!(buf, "{}\n", path);
639
640 map[module].scope.dump(db, buf);
641
642 for (name, child) in map[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
643 {
644 let path = format!("{path}::{}", name.display(db, Edition::LATEST));
645 buf.push('\n');
646 go(buf, db, map, &path, *child);
647 }
648 }
649 }
650}
651
652impl DefMap {
653 pub(crate) fn block_id(&self) -> Option<BlockId> {
654 self.block.map(|block| block.block)
655 }
656
657 pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
658 self.prelude
659 }
660
661 pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
662 &self.macro_use_prelude
663 }
664
665 pub(crate) fn resolve_path(
666 &self,
667 local_def_map: &LocalDefMap,
668 db: &dyn DefDatabase,
669 original_module: ModuleId,
670 path: &ModPath,
671 shadow: BuiltinShadowMode,
672 expected_macro_subns: Option<MacroSubNs>,
673 ) -> (PerNs, Option<usize>) {
674 let res = self.resolve_path_fp_with_macro(
675 local_def_map,
676 db,
677 ResolveMode::Other,
678 original_module,
679 path,
680 shadow,
681 expected_macro_subns,
682 );
683 (res.resolved_def, res.segment_index)
684 }
685
686 pub(crate) fn resolve_path_locally(
689 &self,
690 local_def_map: &LocalDefMap,
691 db: &dyn DefDatabase,
692 original_module: ModuleId,
693 path: &ModPath,
694 shadow: BuiltinShadowMode,
695 ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
696 let res = self.resolve_path_fp_with_macro_single(
697 local_def_map,
698 db,
699 ResolveMode::Other,
700 original_module,
701 path,
702 shadow,
703 None, );
705 (res.resolved_def, res.segment_index, res.prefix_info)
706 }
707
708 pub(crate) fn with_ancestor_maps<T>(
713 &self,
714 db: &dyn DefDatabase,
715 local_mod: ModuleId,
716 f: &mut dyn FnMut(&DefMap, ModuleId) -> Option<T>,
717 ) -> Option<T> {
718 if let Some(it) = f(self, local_mod) {
719 return Some(it);
720 }
721 let mut block = self.block;
722 while let Some(block_info) = block {
723 let parent = block_info.parent.def_map(db);
724 if let Some(it) = f(parent, block_info.parent) {
725 return Some(it);
726 }
727 block = parent.block;
728 }
729
730 None
731 }
732}
733
734impl ModuleData {
735 pub(crate) fn new(
736 origin: ModuleOrigin,
737 visibility: Visibility,
738 parent: Option<ModuleId>,
739 ) -> Self {
740 ModuleData {
741 origin,
742 visibility,
743 parent,
744 children: Default::default(),
745 scope: ItemScope::default(),
746 }
747 }
748
749 pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
751 self.origin.definition_source(db)
752 }
753
754 pub fn definition_source_file_id(&self) -> HirFileId {
756 match self.origin {
757 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
758 definition.into()
759 }
760 ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
761 ModuleOrigin::BlockExpr { block, .. } => block.file_id,
762 }
763 }
764
765 pub fn definition_source_range(&self, db: &dyn DefDatabase) -> InFile<TextRange> {
766 match &self.origin {
767 &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
768 InFile::new(
769 definition.into(),
770 ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db),
771 )
772 }
773 &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
774 definition_tree_id.file_id(),
775 AstId::new(definition_tree_id.file_id(), definition).to_range(db),
776 ),
777 ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)),
778 }
779 }
780
781 pub fn declaration_source(&self, db: &dyn DefDatabase) -> Option<InFile<ast::Module>> {
784 let decl = self.origin.declaration()?;
785 let value = decl.to_node(db);
786 Some(InFile { file_id: decl.file_id, value })
787 }
788
789 pub fn declaration_source_range(&self, db: &dyn DefDatabase) -> Option<InFile<TextRange>> {
792 let decl = self.origin.declaration()?;
793 Some(InFile { file_id: decl.file_id, value: decl.to_range(db) })
794 }
795}
796
797#[derive(Debug, Clone, PartialEq, Eq)]
798pub enum ModuleSource {
799 SourceFile(ast::SourceFile),
800 Module(ast::Module),
801 BlockExpr(ast::BlockExpr),
802}
803
804impl ModuleSource {
805 pub fn node(&self) -> SyntaxNode {
806 match self {
807 ModuleSource::SourceFile(it) => it.syntax().clone(),
808 ModuleSource::Module(it) => it.syntax().clone(),
809 ModuleSource::BlockExpr(it) => it.syntax().clone(),
810 }
811 }
812}
813
814#[derive(Clone, Copy, PartialEq, Eq)]
816pub enum MacroSubNs {
817 Bang,
819 Attr,
821}
822
823pub(crate) fn macro_styles_from_id(db: &dyn DefDatabase, macro_id: MacroId) -> MacroCallStyles {
824 let expander = match macro_id {
825 MacroId::Macro2Id(it) => it.lookup(db).expander,
826 MacroId::MacroRulesId(it) => it.lookup(db).expander,
827 MacroId::ProcMacroId(it) => {
828 return match it.lookup(db).kind {
829 ProcMacroKind::CustomDerive => MacroCallStyles::DERIVE,
830 ProcMacroKind::Bang => MacroCallStyles::FN_LIKE,
831 ProcMacroKind::Attr => MacroCallStyles::ATTR,
832 };
833 }
834 };
835
836 match expander {
837 MacroExpander::Declarative { styles } => styles,
838 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroCallStyles::FN_LIKE,
840 MacroExpander::BuiltInAttr(_) => MacroCallStyles::ATTR,
841 MacroExpander::BuiltInDerive(_) => MacroCallStyles::DERIVE,
842 }
843}
844
845fn sub_namespace_match(
852 db: &dyn DefDatabase,
853 macro_id: MacroId,
854 expected: Option<MacroSubNs>,
855) -> bool {
856 let candidate = macro_styles_from_id(db, macro_id);
857 match expected {
858 Some(MacroSubNs::Bang) => candidate.contains(MacroCallStyles::FN_LIKE),
859 Some(MacroSubNs::Attr) => {
860 candidate.contains(MacroCallStyles::ATTR) || candidate.contains(MacroCallStyles::DERIVE)
861 }
862 None => true,
865 }
866}
867
868#[derive(Debug, PartialEq, Eq)]
870pub struct ModulesMap {
871 inner: FxIndexMap<ModuleId, ModuleData>,
872}
873
874impl ModulesMap {
875 fn new() -> Self {
876 Self { inner: FxIndexMap::default() }
877 }
878
879 fn iter(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
880 self.inner.iter().map(|(&k, v)| (k, v))
881 }
882
883 fn iter_mut(&mut self) -> impl Iterator<Item = (ModuleId, &mut ModuleData)> + '_ {
884 self.inner.iter_mut().map(|(&k, v)| (k, v))
885 }
886}
887
888impl Deref for ModulesMap {
889 type Target = FxIndexMap<ModuleId, ModuleData>;
890
891 fn deref(&self) -> &Self::Target {
892 &self.inner
893 }
894}
895
896impl DerefMut for ModulesMap {
897 fn deref_mut(&mut self) -> &mut Self::Target {
898 &mut self.inner
899 }
900}
901
902impl Index<ModuleId> for ModulesMap {
903 type Output = ModuleData;
904
905 fn index(&self, id: ModuleId) -> &ModuleData {
906 self.inner.get(&id).unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
907 }
908}
909
910impl IndexMut<ModuleId> for ModulesMap {
911 fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
912 self.inner
913 .get_mut(&id)
914 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
915 }
916}