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 hir_expand::{
65 EditionedFileId, ErasedAstId, HirFileId, InFile, MacroCallId, mod_path::ModPath, name::Name,
66 proc_macro::ProcMacroKind,
67};
68use intern::Symbol;
69use itertools::Itertools;
70use rustc_hash::{FxHashMap, FxHashSet};
71use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
72use stdx::format_to;
73use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast};
74use triomphe::Arc;
75use tt::TextRange;
76
77use crate::{
78 AstId, BlockId, BlockLoc, ExternCrateId, FunctionId, FxIndexMap, Lookup, MacroCallStyles,
79 MacroExpander, MacroId, ModuleId, ModuleIdLt, ProcMacroId, UseId,
80 db::DefDatabase,
81 item_scope::{BuiltinShadowMode, ItemScope},
82 item_tree::TreeId,
83 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
84 per_ns::PerNs,
85 visibility::{Visibility, VisibilityExplicitness},
86};
87
88pub use self::path_resolution::ResolvePathResultPrefixInfo;
89
90const PREDEFINED_TOOLS: &[SmolStr] = &[
91 SmolStr::new_static("clippy"),
92 SmolStr::new_static("rustfmt"),
93 SmolStr::new_static("diagnostic"),
94 SmolStr::new_static("miri"),
95 SmolStr::new_static("rust_analyzer"),
96];
97
98#[derive(Debug, PartialEq, Eq, Default)]
107pub struct LocalDefMap {
108 extern_prelude: FxIndexMap<Name, (ModuleId, Option<ExternCrateId>)>,
112}
113
114impl std::hash::Hash for LocalDefMap {
115 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
116 let LocalDefMap { extern_prelude } = self;
117 extern_prelude.len().hash(state);
118 for (name, (crate_root, extern_crate)) in extern_prelude {
119 name.hash(state);
120 crate_root.hash(state);
121 extern_crate.hash(state);
122 }
123 }
124}
125
126impl LocalDefMap {
127 pub(crate) const EMPTY: &Self =
128 &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) };
129
130 fn shrink_to_fit(&mut self) {
131 let Self { extern_prelude } = self;
132 extern_prelude.shrink_to_fit();
133 }
134
135 pub(crate) fn extern_prelude(
136 &self,
137 ) -> impl DoubleEndedIterator<Item = (&Name, (ModuleId, Option<ExternCrateId>))> + '_ {
138 self.extern_prelude.iter().map(|(name, &def)| (name, def))
139 }
140}
141
142#[derive(Debug, PartialEq, Eq)]
152pub struct DefMap {
153 krate: Crate,
155 block: Option<BlockInfo>,
158 pub root: ModuleId,
159 pub modules: ModulesMap,
161 prelude: Option<(ModuleId, Option<UseId>)>,
168 macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
172
173 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>,
177 pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>,
179
180 diagnostics: Vec<DefDiagnostic>,
182
183 data: Arc<DefMapCrateData>,
185}
186
187#[derive(Clone, Debug, PartialEq, Eq)]
189struct DefMapCrateData {
190 exported_derives: FxHashMap<MacroId, Box<[Name]>>,
192 fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
193
194 registered_tools: Vec<Symbol>,
196 unstable_features: FxHashSet<Symbol>,
198 rustc_coherence_is_core: bool,
200 no_core: bool,
201 no_std: bool,
202
203 edition: Edition,
204 recursion_limit: Option<u32>,
205}
206
207impl DefMapCrateData {
208 fn new(edition: Edition) -> Self {
209 Self {
210 exported_derives: FxHashMap::default(),
211 fn_proc_macro_mapping: FxHashMap::default(),
212 registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
213 unstable_features: FxHashSet::default(),
214 rustc_coherence_is_core: false,
215 no_core: false,
216 no_std: false,
217 edition,
218 recursion_limit: None,
219 }
220 }
221
222 fn shrink_to_fit(&mut self) {
223 let Self {
224 exported_derives,
225 fn_proc_macro_mapping,
226 registered_tools,
227 unstable_features,
228 rustc_coherence_is_core: _,
229 no_core: _,
230 no_std: _,
231 edition: _,
232 recursion_limit: _,
233 } = self;
234 exported_derives.shrink_to_fit();
235 fn_proc_macro_mapping.shrink_to_fit();
236 registered_tools.shrink_to_fit();
237 unstable_features.shrink_to_fit();
238 }
239}
240
241#[derive(Debug, PartialEq, Eq, Clone, Copy)]
243struct BlockInfo {
244 block: BlockId,
246 parent: ModuleId,
248}
249
250impl std::ops::Index<ModuleId> for DefMap {
251 type Output = ModuleData;
252
253 fn index(&self, id: ModuleId) -> &ModuleData {
254 self.modules
255 .get(&id)
256 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap {:#?}: {id:#?}", self.root))
257 }
258}
259
260impl std::ops::IndexMut<ModuleId> for DefMap {
261 fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
262 &mut self.modules[id]
263 }
264}
265
266#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
267pub enum ModuleOrigin {
268 CrateRoot {
269 definition: EditionedFileId,
270 },
271 File {
273 is_mod_rs: bool,
274 declaration: FileAstId<ast::Module>,
275 declaration_tree_id: TreeId,
276 definition: EditionedFileId,
277 },
278 Inline {
279 definition_tree_id: TreeId,
280 definition: FileAstId<ast::Module>,
281 },
282 BlockExpr {
284 id: BlockId,
285 block: AstId<ast::BlockExpr>,
286 },
287}
288
289impl ModuleOrigin {
290 pub fn declaration(&self) -> Option<AstId<ast::Module>> {
291 match self {
292 &ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
293 Some(AstId::new(declaration_tree_id.file_id(), declaration))
294 }
295 &ModuleOrigin::Inline { definition, definition_tree_id } => {
296 Some(AstId::new(definition_tree_id.file_id(), definition))
297 }
298 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
299 }
300 }
301
302 pub fn file_id(&self) -> Option<EditionedFileId> {
303 match self {
304 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
305 Some(*definition)
306 }
307 _ => None,
308 }
309 }
310
311 pub fn is_inline(&self) -> bool {
312 match self {
313 ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
314 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
315 }
316 }
317
318 pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
321 match self {
322 &ModuleOrigin::File { definition: editioned_file_id, .. }
323 | &ModuleOrigin::CrateRoot { definition: editioned_file_id } => {
324 let sf = db.parse(editioned_file_id).tree();
325 InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf))
326 }
327 &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
328 definition_tree_id.file_id(),
329 ModuleSource::Module(
330 AstId::new(definition_tree_id.file_id(), definition).to_node(db),
331 ),
332 ),
333 ModuleOrigin::BlockExpr { block, .. } => {
334 InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db)))
335 }
336 }
337 }
338}
339
340#[derive(Debug, PartialEq, Eq)]
341pub struct ModuleData {
342 pub origin: ModuleOrigin,
344 pub visibility: Visibility,
346 pub parent: Option<ModuleId>,
350 pub children: FxIndexMap<Name, ModuleId>,
351 pub scope: ItemScope,
352}
353
354#[inline]
355pub fn crate_def_map(db: &dyn DefDatabase, crate_id: Crate) -> &DefMap {
356 crate_local_def_map(db, crate_id).def_map(db)
357}
358
359#[salsa_macros::tracked]
360pub(crate) struct DefMapPair<'db> {
361 #[tracked]
362 #[returns(ref)]
363 pub(crate) def_map: DefMap,
364 #[returns(ref)]
365 pub(crate) local: LocalDefMap,
366}
367
368#[salsa_macros::tracked(returns(ref))]
369pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> {
370 let krate = crate_id.data(db);
371 let _p = tracing::info_span!(
372 "crate_def_map_query",
373 name=?crate_id
374 .extra_data(db)
375 .display_name
376 .as_ref()
377 .map(|it| it.crate_name().to_smolstr())
378 .unwrap_or_default()
379 )
380 .entered();
381
382 let root_file_id = crate_id.root_file_id(db);
383 let module_data = ModuleData::new(
384 ModuleOrigin::CrateRoot { definition: root_file_id },
385 Visibility::Public,
386 None,
387 );
388
389 let def_map = DefMap::empty(
390 db,
391 crate_id,
392 Arc::new(DefMapCrateData::new(krate.edition)),
393 module_data,
394 None,
395 );
396 let (def_map, local_def_map) =
397 collector::collect_defs(db, def_map, TreeId::new(root_file_id.into(), None), None);
398
399 DefMapPair::new(db, def_map, local_def_map)
400}
401
402#[salsa_macros::tracked(returns(ref))]
403pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
404 let BlockLoc { ast_id, module } = block_id.lookup(db);
405
406 let visibility = Visibility::Module(module, VisibilityExplicitness::Implicit);
407 let module_data =
408 ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility, None);
409
410 let krate = module.krate(db);
411 let local_def_map = crate_local_def_map(db, krate);
412 let def_map = DefMap::empty(
413 db,
414 krate,
415 local_def_map.def_map(db).data.clone(),
416 module_data,
417 Some(BlockInfo { block: block_id, parent: module }),
418 );
419
420 let (def_map, _) = collector::collect_defs(
421 db,
422 def_map,
423 TreeId::new(ast_id.file_id, Some(block_id)),
424 Some(local_def_map.local(db)),
425 );
426 def_map
427}
428
429impl DefMap {
430 pub fn edition(&self) -> Edition {
431 self.data.edition
432 }
433
434 fn empty(
435 db: &dyn DefDatabase,
436 krate: Crate,
437 crate_data: Arc<DefMapCrateData>,
438 module_data: ModuleData,
439 block: Option<BlockInfo>,
440 ) -> DefMap {
441 let mut modules = ModulesMap::new();
442 let root = unsafe { ModuleIdLt::new(db, krate, block.map(|it| it.block)).to_static() };
443 modules.insert(root, module_data);
444
445 DefMap {
446 block,
447 root,
448 modules,
449 krate,
450 prelude: None,
451 macro_use_prelude: FxHashMap::default(),
452 derive_helpers_in_scope: FxHashMap::default(),
453 diagnostics: Vec::new(),
454 data: crate_data,
455 macro_def_to_macro_id: FxHashMap::default(),
456 }
457 }
458 fn shrink_to_fit(&mut self) {
459 let Self {
461 macro_use_prelude,
462 diagnostics,
463 modules,
464 derive_helpers_in_scope,
465 root: _,
466 block: _,
467 krate: _,
468 prelude: _,
469 data: _,
470 macro_def_to_macro_id,
471 } = self;
472
473 macro_def_to_macro_id.shrink_to_fit();
474 macro_use_prelude.shrink_to_fit();
475 diagnostics.shrink_to_fit();
476 modules.shrink_to_fit();
477 derive_helpers_in_scope.shrink_to_fit();
478 for (_, module) in modules.iter_mut() {
479 module.children.shrink_to_fit();
480 module.scope.shrink_to_fit();
481 }
482 }
483}
484
485impl DefMap {
486 pub fn modules_for_file<'a>(
487 &'a self,
488 db: &'a dyn DefDatabase,
489 file_id: FileId,
490 ) -> impl Iterator<Item = ModuleId> + 'a {
491 self.modules
492 .iter()
493 .filter(move |(_id, data)| {
494 data.origin.file_id().map(|file_id| file_id.file_id(db)) == Some(file_id)
495 })
496 .map(|(id, _data)| id)
497 }
498
499 pub fn modules(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
500 self.modules.iter()
501 }
502
503 pub fn derive_helpers_in_scope(
504 &self,
505 id: AstId<ast::Adt>,
506 ) -> Option<&[(Name, MacroId, MacroCallId)]> {
507 self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref)
508 }
509
510 pub fn registered_tools(&self) -> &[Symbol] {
511 &self.data.registered_tools
512 }
513
514 pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
515 self.data.unstable_features.contains(feature)
516 }
517
518 pub fn is_rustc_coherence_is_core(&self) -> bool {
519 self.data.rustc_coherence_is_core
520 }
521
522 pub fn is_no_std(&self) -> bool {
523 self.data.no_std || self.data.no_core
524 }
525
526 pub fn is_no_core(&self) -> bool {
527 self.data.no_core
528 }
529
530 pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
531 self.data.fn_proc_macro_mapping.get(&id).copied()
532 }
533
534 pub fn krate(&self) -> Crate {
535 self.krate
536 }
537
538 #[inline]
539 pub fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId {
540 match self.block {
541 Some(_) => crate_def_map(db, self.krate()).root,
542 None => self.root,
543 }
544 }
545
546 pub fn root_module_id(&self) -> ModuleId {
549 self.root
550 }
551
552 pub fn parent(&self) -> Option<ModuleId> {
555 Some(self.block?.parent)
556 }
557
558 pub fn containing_module(&self, local_mod: ModuleId) -> Option<ModuleId> {
561 match self[local_mod].parent {
562 Some(parent) => Some(parent),
563 None => self.block.map(|BlockInfo { parent, .. }| parent),
564 }
565 }
566
567 pub fn diagnostics(&self) -> &[DefDiagnostic] {
569 self.diagnostics.as_slice()
570 }
571
572 pub fn recursion_limit(&self) -> u32 {
573 self.data.recursion_limit.unwrap_or(128)
575 }
576
577 pub fn dump(&self, db: &dyn DefDatabase) -> String {
580 let mut buf = String::new();
581 let mut current_map = self;
582 while let Some(block) = current_map.block {
583 go(&mut buf, db, current_map, "(block scope)", current_map.root);
584 buf.push('\n');
585 current_map = block.parent.def_map(db);
586 }
587 go(&mut buf, db, current_map, "crate", current_map.root);
588 return buf;
589
590 fn go(buf: &mut String, db: &dyn DefDatabase, map: &DefMap, path: &str, module: ModuleId) {
591 format_to!(buf, "{}\n", path);
592
593 map[module].scope.dump(db, buf);
594
595 for (name, child) in map[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
596 {
597 let path = format!("{path}::{}", name.display(db, Edition::LATEST));
598 buf.push('\n');
599 go(buf, db, map, &path, *child);
600 }
601 }
602 }
603}
604
605impl DefMap {
606 pub(crate) fn block_id(&self) -> Option<BlockId> {
607 self.block.map(|block| block.block)
608 }
609
610 pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
611 self.prelude
612 }
613
614 pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
615 &self.macro_use_prelude
616 }
617
618 pub(crate) fn resolve_path(
619 &self,
620 local_def_map: &LocalDefMap,
621 db: &dyn DefDatabase,
622 original_module: ModuleId,
623 path: &ModPath,
624 shadow: BuiltinShadowMode,
625 expected_macro_subns: Option<MacroSubNs>,
626 ) -> (PerNs, Option<usize>) {
627 let res = self.resolve_path_fp_with_macro(
628 local_def_map,
629 db,
630 ResolveMode::Other,
631 original_module,
632 path,
633 shadow,
634 expected_macro_subns,
635 );
636 (res.resolved_def, res.segment_index)
637 }
638
639 pub(crate) fn resolve_path_locally(
642 &self,
643 local_def_map: &LocalDefMap,
644 db: &dyn DefDatabase,
645 original_module: ModuleId,
646 path: &ModPath,
647 shadow: BuiltinShadowMode,
648 ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
649 let res = self.resolve_path_fp_with_macro_single(
650 local_def_map,
651 db,
652 ResolveMode::Other,
653 original_module,
654 path,
655 shadow,
656 None, );
658 (res.resolved_def, res.segment_index, res.prefix_info)
659 }
660
661 pub(crate) fn with_ancestor_maps<T>(
666 &self,
667 db: &dyn DefDatabase,
668 local_mod: ModuleId,
669 f: &mut dyn FnMut(&DefMap, ModuleId) -> Option<T>,
670 ) -> Option<T> {
671 if let Some(it) = f(self, local_mod) {
672 return Some(it);
673 }
674 let mut block = self.block;
675 while let Some(block_info) = block {
676 let parent = block_info.parent.def_map(db);
677 if let Some(it) = f(parent, block_info.parent) {
678 return Some(it);
679 }
680 block = parent.block;
681 }
682
683 None
684 }
685}
686
687impl ModuleData {
688 pub(crate) fn new(
689 origin: ModuleOrigin,
690 visibility: Visibility,
691 parent: Option<ModuleId>,
692 ) -> Self {
693 ModuleData {
694 origin,
695 visibility,
696 parent,
697 children: Default::default(),
698 scope: ItemScope::default(),
699 }
700 }
701
702 pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
704 self.origin.definition_source(db)
705 }
706
707 pub fn definition_source_file_id(&self) -> HirFileId {
709 match self.origin {
710 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
711 definition.into()
712 }
713 ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
714 ModuleOrigin::BlockExpr { block, .. } => block.file_id,
715 }
716 }
717
718 pub fn definition_source_range(&self, db: &dyn DefDatabase) -> InFile<TextRange> {
719 match &self.origin {
720 &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
721 InFile::new(
722 definition.into(),
723 ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db),
724 )
725 }
726 &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
727 definition_tree_id.file_id(),
728 AstId::new(definition_tree_id.file_id(), definition).to_range(db),
729 ),
730 ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)),
731 }
732 }
733
734 pub fn declaration_source(&self, db: &dyn DefDatabase) -> Option<InFile<ast::Module>> {
737 let decl = self.origin.declaration()?;
738 let value = decl.to_node(db);
739 Some(InFile { file_id: decl.file_id, value })
740 }
741
742 pub fn declaration_source_range(&self, db: &dyn DefDatabase) -> Option<InFile<TextRange>> {
745 let decl = self.origin.declaration()?;
746 Some(InFile { file_id: decl.file_id, value: decl.to_range(db) })
747 }
748}
749
750#[derive(Debug, Clone, PartialEq, Eq)]
751pub enum ModuleSource {
752 SourceFile(ast::SourceFile),
753 Module(ast::Module),
754 BlockExpr(ast::BlockExpr),
755}
756
757impl ModuleSource {
758 pub fn node(&self) -> SyntaxNode {
759 match self {
760 ModuleSource::SourceFile(it) => it.syntax().clone(),
761 ModuleSource::Module(it) => it.syntax().clone(),
762 ModuleSource::BlockExpr(it) => it.syntax().clone(),
763 }
764 }
765}
766
767#[derive(Clone, Copy, PartialEq, Eq)]
769pub enum MacroSubNs {
770 Bang,
772 Attr,
774}
775
776pub(crate) fn macro_styles_from_id(db: &dyn DefDatabase, macro_id: MacroId) -> MacroCallStyles {
777 let expander = match macro_id {
778 MacroId::Macro2Id(it) => it.lookup(db).expander,
779 MacroId::MacroRulesId(it) => it.lookup(db).expander,
780 MacroId::ProcMacroId(it) => {
781 return match it.lookup(db).kind {
782 ProcMacroKind::CustomDerive => MacroCallStyles::DERIVE,
783 ProcMacroKind::Bang => MacroCallStyles::FN_LIKE,
784 ProcMacroKind::Attr => MacroCallStyles::ATTR,
785 };
786 }
787 };
788
789 match expander {
790 MacroExpander::Declarative { styles } => styles,
791 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroCallStyles::FN_LIKE,
793 MacroExpander::BuiltInAttr(_) => MacroCallStyles::ATTR,
794 MacroExpander::BuiltInDerive(_) => MacroCallStyles::DERIVE,
795 }
796}
797
798fn sub_namespace_match(
805 db: &dyn DefDatabase,
806 macro_id: MacroId,
807 expected: Option<MacroSubNs>,
808) -> bool {
809 let candidate = macro_styles_from_id(db, macro_id);
810 match expected {
811 Some(MacroSubNs::Bang) => candidate.contains(MacroCallStyles::FN_LIKE),
812 Some(MacroSubNs::Attr) => {
813 candidate.contains(MacroCallStyles::ATTR) || candidate.contains(MacroCallStyles::DERIVE)
814 }
815 None => true,
818 }
819}
820
821#[derive(Debug, PartialEq, Eq)]
823pub struct ModulesMap {
824 inner: FxIndexMap<ModuleId, ModuleData>,
825}
826
827impl ModulesMap {
828 fn new() -> Self {
829 Self { inner: FxIndexMap::default() }
830 }
831
832 fn iter(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
833 self.inner.iter().map(|(&k, v)| (k, v))
834 }
835
836 fn iter_mut(&mut self) -> impl Iterator<Item = (ModuleId, &mut ModuleData)> + '_ {
837 self.inner.iter_mut().map(|(&k, v)| (k, v))
838 }
839}
840
841impl Deref for ModulesMap {
842 type Target = FxIndexMap<ModuleId, ModuleData>;
843
844 fn deref(&self) -> &Self::Target {
845 &self.inner
846 }
847}
848
849impl DerefMut for ModulesMap {
850 fn deref_mut(&mut self) -> &mut Self::Target {
851 &mut self.inner
852 }
853}
854
855impl Index<ModuleId> for ModulesMap {
856 type Output = ModuleData;
857
858 fn index(&self, id: ModuleId) -> &ModuleData {
859 self.inner.get(&id).unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
860 }
861}
862
863impl IndexMut<ModuleId> for ModulesMap {
864 fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
865 self.inner
866 .get_mut(&id)
867 .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
868 }
869}