aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/crate_def_map
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/crate_def_map')
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/collector.rs166
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/raw.rs51
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests.rs2
3 files changed, 132 insertions, 87 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
index cd328b755..2fbfa9e34 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
@@ -1,42 +1,25 @@
1use std::sync::Arc; 1use arrayvec::ArrayVec;
2
3use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
4use ra_arena::Arena; 3use relative_path::RelativePathBuf;
5use test_utils::tested_by; 4use test_utils::tested_by;
5use ra_db::FileId;
6 6
7use crate::{ 7use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 Crate, PersistentHirDatabase, HirFileId, Name, Path, 9 PersistentHirDatabase, HirFileId, Name, Path, Problem,
10 KnownName, 10 KnownName,
11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, 11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode},
12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId},
13 module_tree::resolve_module_declaration,
14}; 13};
15 14
16use super::{CrateDefMap, ModuleId, ModuleData, raw}; 15use super::{CrateDefMap, ModuleId, ModuleData, raw};
17 16
18#[allow(unused)] 17pub(super) fn collect_defs(
19pub(crate) fn crate_def_map_query(
20 db: &impl PersistentHirDatabase, 18 db: &impl PersistentHirDatabase,
21 krate: Crate, 19 mut def_map: CrateDefMap,
22) -> Arc<CrateDefMap> { 20) -> CrateDefMap {
23 let mut def_map = {
24 let edition = krate.edition(db);
25 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
26 let root = modules.alloc(ModuleData::default());
27 CrateDefMap {
28 krate,
29 edition,
30 extern_prelude: FxHashMap::default(),
31 prelude: None,
32 root,
33 modules,
34 public_macros: FxHashMap::default(),
35 }
36 };
37
38 // populate external prelude 21 // populate external prelude
39 for dep in krate.dependencies(db) { 22 for dep in def_map.krate.dependencies(db) {
40 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); 23 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
41 if let Some(module) = dep.krate.root_module(db) { 24 if let Some(module) = dep.krate.root_module(db) {
42 def_map.extern_prelude.insert(dep.name.clone(), module.into()); 25 def_map.extern_prelude.insert(dep.name.clone(), module.into());
@@ -52,7 +35,6 @@ pub(crate) fn crate_def_map_query(
52 35
53 let mut collector = DefCollector { 36 let mut collector = DefCollector {
54 db, 37 db,
55 krate,
56 def_map, 38 def_map,
57 glob_imports: FxHashMap::default(), 39 glob_imports: FxHashMap::default(),
58 unresolved_imports: Vec::new(), 40 unresolved_imports: Vec::new(),
@@ -60,14 +42,12 @@ pub(crate) fn crate_def_map_query(
60 global_macro_scope: FxHashMap::default(), 42 global_macro_scope: FxHashMap::default(),
61 }; 43 };
62 collector.collect(); 44 collector.collect();
63 let def_map = collector.finish(); 45 collector.finish()
64 Arc::new(def_map)
65} 46}
66 47
67/// Walks the tree of module recursively 48/// Walks the tree of module recursively
68struct DefCollector<DB> { 49struct DefCollector<DB> {
69 db: DB, 50 db: DB,
70 krate: Crate,
71 def_map: CrateDefMap, 51 def_map: CrateDefMap,
72 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>, 52 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>,
73 unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>, 53 unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>,
@@ -75,23 +55,16 @@ struct DefCollector<DB> {
75 global_macro_scope: FxHashMap<Name, mbe::MacroRules>, 55 global_macro_scope: FxHashMap<Name, mbe::MacroRules>,
76} 56}
77 57
78/// Walks a single module, populating defs, imports and macros
79struct ModCollector<'a, D> {
80 def_collector: D,
81 module_id: ModuleId,
82 file_id: HirFileId,
83 raw_items: &'a raw::RawItems,
84}
85
86impl<'a, DB> DefCollector<&'a DB> 58impl<'a, DB> DefCollector<&'a DB>
87where 59where
88 DB: PersistentHirDatabase, 60 DB: PersistentHirDatabase,
89{ 61{
90 fn collect(&mut self) { 62 fn collect(&mut self) {
91 let crate_graph = self.db.crate_graph(); 63 let crate_graph = self.db.crate_graph();
92 let file_id = crate_graph.crate_root(self.krate.crate_id()); 64 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
93 let raw_items = raw::RawItems::raw_items_query(self.db, file_id); 65 let raw_items = self.db.raw_items(file_id);
94 let module_id = self.def_map.root; 66 let module_id = self.def_map.root;
67 self.def_map.modules[module_id].definition = Some(file_id);
95 ModCollector { 68 ModCollector {
96 def_collector: &mut *self, 69 def_collector: &mut *self,
97 module_id, 70 module_id,
@@ -123,10 +96,6 @@ where
123 } 96 }
124 } 97 }
125 98
126 fn alloc_module(&mut self) -> ModuleId {
127 self.def_map.modules.alloc(ModuleData::default())
128 }
129
130 fn resolve_imports(&mut self) -> ReachedFixedPoint { 99 fn resolve_imports(&mut self) -> ReachedFixedPoint {
131 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 100 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
132 let mut resolved = Vec::new(); 101 let mut resolved = Vec::new();
@@ -184,7 +153,7 @@ where
184 if import.is_prelude { 153 if import.is_prelude {
185 tested_by!(std_prelude); 154 tested_by!(std_prelude);
186 self.def_map.prelude = Some(m); 155 self.def_map.prelude = Some(m);
187 } else if m.krate != self.krate { 156 } else if m.krate != self.def_map.krate {
188 tested_by!(glob_across_crates); 157 tested_by!(glob_across_crates);
189 // glob import from other crate => we can just import everything once 158 // glob import from other crate => we can just import everything once
190 let item_map = self.db.item_map(m.krate); 159 let item_map = self.db.item_map(m.krate);
@@ -199,7 +168,7 @@ where
199 // glob import from same crate => we do an initial 168 // glob import from same crate => we do an initial
200 // import, and then need to propagate any further 169 // import, and then need to propagate any further
201 // additions 170 // additions
202 let scope = &self.def_map[m.module_id]; 171 let scope = &self.def_map[m.module_id].scope;
203 let items = scope 172 let items = scope
204 .items 173 .items
205 .iter() 174 .iter()
@@ -243,11 +212,9 @@ where
243 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 212 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
244 213
245 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 214 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
246 if let Some(root_module) = self.krate.root_module(self.db) { 215 if import.is_extern_crate && module_id == self.def_map.root {
247 if import.is_extern_crate && module_id == root_module.module_id { 216 if let Some(def) = def.take_types() {
248 if let Some(def) = def.take_types() { 217 self.def_map.extern_prelude.insert(name.clone(), def);
249 self.def_map.extern_prelude.insert(name.clone(), def);
250 }
251 } 218 }
252 } 219 }
253 let resolution = Resolution { def, import: Some(import_id) }; 220 let resolution = Resolution { def, import: Some(import_id) };
@@ -324,8 +291,7 @@ where
324 Some(it) => it, 291 Some(it) => it,
325 _ => return true, 292 _ => return true,
326 }; 293 };
327 // FIXME: this should be a proper query 294 let def_map = self.db.crate_def_map(krate);
328 let def_map = crate_def_map_query(self.db, krate);
329 let rules = def_map.public_macros.get(&path.segments[1].name).cloned(); 295 let rules = def_map.public_macros.get(&path.segments[1].name).cloned();
330 resolved.push((*module_id, *call_id, rules, tt.clone())); 296 resolved.push((*module_id, *call_id, rules, tt.clone()));
331 false 297 false
@@ -367,6 +333,14 @@ where
367 } 333 }
368} 334}
369 335
336/// Walks a single module, populating defs, imports and macros
337struct ModCollector<'a, D> {
338 def_collector: D,
339 module_id: ModuleId,
340 file_id: HirFileId,
341 raw_items: &'a raw::RawItems,
342}
343
370impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 344impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
371where 345where
372 DB: PersistentHirDatabase, 346 DB: PersistentHirDatabase,
@@ -389,8 +363,12 @@ where
389 fn collect_module(&mut self, module: &raw::ModuleData) { 363 fn collect_module(&mut self, module: &raw::ModuleData) {
390 match module { 364 match module {
391 // inline module, just recurse 365 // inline module, just recurse
392 raw::ModuleData::Definition { name, items } => { 366 raw::ModuleData::Definition { name, items, source_item_id } => {
393 let module_id = self.push_child_module(name.clone()); 367 let module_id = self.push_child_module(
368 name.clone(),
369 source_item_id.with_file_id(self.file_id),
370 None,
371 );
394 ModCollector { 372 ModCollector {
395 def_collector: &mut *self.def_collector, 373 def_collector: &mut *self.def_collector,
396 module_id, 374 module_id,
@@ -400,13 +378,20 @@ where
400 .collect(&*items); 378 .collect(&*items);
401 } 379 }
402 // out of line module, resovle, parse and recurse 380 // out of line module, resovle, parse and recurse
403 raw::ModuleData::Declaration { name } => { 381 raw::ModuleData::Declaration { name, source_item_id } => {
404 let module_id = self.push_child_module(name.clone()); 382 let source_item_id = source_item_id.with_file_id(self.file_id);
405 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 383 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
406 if let Some(file_id) = 384 let (file_ids, problem) =
407 resolve_module_declaration(self.def_collector.db, self.file_id, name, is_root) 385 resolve_submodule(self.def_collector.db, self.file_id, name, is_root);
408 { 386
409 let raw_items = raw::RawItems::raw_items_query(self.def_collector.db, file_id); 387 if let Some(problem) = problem {
388 self.def_collector.def_map.problems.add(source_item_id, problem)
389 }
390
391 if let Some(&file_id) = file_ids.first() {
392 let module_id =
393 self.push_child_module(name.clone(), source_item_id, Some(file_id));
394 let raw_items = self.def_collector.db.raw_items(file_id);
410 ModCollector { 395 ModCollector {
411 def_collector: &mut *self.def_collector, 396 def_collector: &mut *self.def_collector,
412 module_id, 397 module_id,
@@ -419,15 +404,23 @@ where
419 } 404 }
420 } 405 }
421 406
422 fn push_child_module(&mut self, name: Name) -> ModuleId { 407 fn push_child_module(
423 let res = self.def_collector.alloc_module(); 408 &mut self,
424 self.def_collector.def_map.modules[res].parent = Some(self.module_id); 409 name: Name,
425 self.def_collector.def_map.modules[self.module_id].children.insert(name, res); 410 declaration: SourceItemId,
411 definition: Option<FileId>,
412 ) -> ModuleId {
413 let modules = &mut self.def_collector.def_map.modules;
414 let res = modules.alloc(ModuleData::default());
415 modules[res].parent = Some(self.module_id);
416 modules[res].declaration = Some(declaration);
417 modules[res].definition = definition;
418 modules[self.module_id].children.insert(name, res);
426 res 419 res
427 } 420 }
428 421
429 fn define_def(&mut self, def: &raw::DefData) { 422 fn define_def(&mut self, def: &raw::DefData) {
430 let module = Module { krate: self.def_collector.krate, module_id: self.module_id }; 423 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
431 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); 424 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
432 macro_rules! id { 425 macro_rules! id {
433 () => { 426 () => {
@@ -462,7 +455,7 @@ where
462 455
463 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 456 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id };
464 let macro_call_id = MacroCallLoc { 457 let macro_call_id = MacroCallLoc {
465 module: Module { krate: self.def_collector.krate, module_id: self.module_id }, 458 module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id },
466 source_item_id, 459 source_item_id,
467 } 460 }
468 .id(self.def_collector.db); 461 .id(self.def_collector.db);
@@ -491,3 +484,44 @@ where
491fn is_macro_rules(path: &Path) -> bool { 484fn is_macro_rules(path: &Path) -> bool {
492 path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules) 485 path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules)
493} 486}
487
488fn resolve_submodule(
489 db: &impl PersistentHirDatabase,
490 file_id: HirFileId,
491 name: &Name,
492 is_root: bool,
493) -> (Vec<FileId>, Option<Problem>) {
494 // FIXME: handle submodules of inline modules properly
495 let file_id = file_id.original_file(db);
496 let source_root_id = db.file_source_root(file_id);
497 let path = db.file_relative_path(file_id);
498 let root = RelativePathBuf::default();
499 let dir_path = path.parent().unwrap_or(&root);
500 let mod_name = path.file_stem().unwrap_or("unknown");
501 let is_dir_owner = is_root || mod_name == "mod";
502
503 let file_mod = dir_path.join(format!("{}.rs", name));
504 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
505 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
506 let mut candidates = ArrayVec::<[_; 2]>::new();
507 if is_dir_owner {
508 candidates.push(file_mod.clone());
509 candidates.push(dir_mod);
510 } else {
511 candidates.push(file_dir_mod.clone());
512 };
513 let sr = db.source_root(source_root_id);
514 let points_to = candidates
515 .into_iter()
516 .filter_map(|path| sr.files.get(&path))
517 .map(|&it| it)
518 .collect::<Vec<_>>();
519 let problem = if points_to.is_empty() {
520 Some(Problem::UnresolvedModule {
521 candidate: if is_dir_owner { file_mod } else { file_dir_mod },
522 })
523 } else {
524 None
525 };
526 (points_to, problem)
527}
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/crate_def_map/raw.rs
index fe832b8da..f064f722c 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/raw.rs
@@ -3,6 +3,7 @@ use std::{
3 ops::Index, 3 ops::Index,
4}; 4};
5 5
6use test_utils::tested_by;
6use ra_db::FileId; 7use ra_db::FileId;
7use ra_arena::{Arena, impl_arena_id, RawId}; 8use ra_arena::{Arena, impl_arena_id, RawId};
8use ra_syntax::{ 9use ra_syntax::{
@@ -15,8 +16,8 @@ use crate::{
15 ids::{SourceFileItemId, SourceFileItems}, 16 ids::{SourceFileItemId, SourceFileItems},
16}; 17};
17 18
18#[derive(Default, PartialEq, Eq)] 19#[derive(Debug, Default, PartialEq, Eq)]
19pub(crate) struct RawItems { 20pub struct RawItems {
20 modules: Arena<Module, ModuleData>, 21 modules: Arena<Module, ModuleData>,
21 imports: Arena<ImportId, ImportData>, 22 imports: Arena<ImportId, ImportData>,
22 defs: Arena<Def, DefData>, 23 defs: Arena<Def, DefData>,
@@ -26,18 +27,21 @@ pub(crate) struct RawItems {
26} 27}
27 28
28impl RawItems { 29impl RawItems {
29 pub(crate) fn items(&self) -> &[RawItem] { 30 pub(crate) fn raw_items_query(
30 &self.items 31 db: &impl PersistentHirDatabase,
31 } 32 file_id: FileId,
32 33 ) -> Arc<RawItems> {
33 pub(crate) fn raw_items_query(db: &impl PersistentHirDatabase, file_id: FileId) -> RawItems {
34 let mut collector = RawItemsCollector { 34 let mut collector = RawItemsCollector {
35 raw_items: RawItems::default(), 35 raw_items: RawItems::default(),
36 source_file_items: db.file_items(file_id.into()), 36 source_file_items: db.file_items(file_id.into()),
37 }; 37 };
38 let source_file = db.parse(file_id); 38 let source_file = db.parse(file_id);
39 collector.process_module(None, &*source_file); 39 collector.process_module(None, &*source_file);
40 collector.raw_items 40 Arc::new(collector.raw_items)
41 }
42
43 pub(crate) fn items(&self) -> &[RawItem] {
44 &self.items
41 } 45 }
42 46
43 // We can't use queries during name resolution for fear of cycles, so this 47 // We can't use queries during name resolution for fear of cycles, so this
@@ -81,7 +85,7 @@ impl Index<Macro> for RawItems {
81 } 85 }
82} 86}
83 87
84#[derive(PartialEq, Eq, Clone, Copy)] 88#[derive(Debug, PartialEq, Eq, Clone, Copy)]
85pub(crate) enum RawItem { 89pub(crate) enum RawItem {
86 Module(Module), 90 Module(Module),
87 Import(ImportId), 91 Import(ImportId),
@@ -89,24 +93,24 @@ pub(crate) enum RawItem {
89 Macro(Macro), 93 Macro(Macro),
90} 94}
91 95
92#[derive(Clone, Copy, PartialEq, Eq, Hash)] 96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93pub(crate) struct Module(RawId); 97pub(crate) struct Module(RawId);
94impl_arena_id!(Module); 98impl_arena_id!(Module);
95 99
96#[derive(PartialEq, Eq)] 100#[derive(Debug, PartialEq, Eq)]
97pub(crate) enum ModuleData { 101pub(crate) enum ModuleData {
98 Declaration { name: Name }, 102 Declaration { name: Name, source_item_id: SourceFileItemId },
99 Definition { name: Name, items: Vec<RawItem> }, 103 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> },
100} 104}
101 105
102pub(crate) use crate::nameres::lower::ImportId; 106pub(crate) use crate::nameres::lower::ImportId;
103pub(super) use crate::nameres::lower::ImportData; 107pub(super) use crate::nameres::lower::ImportData;
104 108
105#[derive(Clone, Copy, PartialEq, Eq, Hash)] 109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub(crate) struct Def(RawId); 110pub(crate) struct Def(RawId);
107impl_arena_id!(Def); 111impl_arena_id!(Def);
108 112
109#[derive(PartialEq, Eq)] 113#[derive(Debug, PartialEq, Eq)]
110pub(crate) struct DefData { 114pub(crate) struct DefData {
111 pub(crate) source_item_id: SourceFileItemId, 115 pub(crate) source_item_id: SourceFileItemId,
112 pub(crate) name: Name, 116 pub(crate) name: Name,
@@ -124,11 +128,11 @@ pub(crate) enum DefKind {
124 TypeAlias, 128 TypeAlias,
125} 129}
126 130
127#[derive(Clone, Copy, PartialEq, Eq, Hash)] 131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128pub(crate) struct Macro(RawId); 132pub(crate) struct Macro(RawId);
129impl_arena_id!(Macro); 133impl_arena_id!(Macro);
130 134
131#[derive(PartialEq, Eq)] 135#[derive(Debug, PartialEq, Eq)]
132pub(crate) struct MacroData { 136pub(crate) struct MacroData {
133 pub(crate) source_item_id: SourceFileItemId, 137 pub(crate) source_item_id: SourceFileItemId,
134 pub(crate) path: Path, 138 pub(crate) path: Path,
@@ -191,18 +195,25 @@ impl RawItemsCollector {
191 Some(it) => it.as_name(), 195 Some(it) => it.as_name(),
192 None => return, 196 None => return,
193 }; 197 };
198 let source_item_id = self.source_file_items.id_of_unchecked(module.syntax());
194 if module.has_semi() { 199 if module.has_semi() {
195 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name }); 200 let item =
201 self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
196 self.push_item(current_module, RawItem::Module(item)); 202 self.push_item(current_module, RawItem::Module(item));
197 return; 203 return;
198 } 204 }
199 205
200 if let Some(item_list) = module.item_list() { 206 if let Some(item_list) = module.item_list() {
201 let item = 207 let item = self.raw_items.modules.alloc(ModuleData::Definition {
202 self.raw_items.modules.alloc(ModuleData::Definition { name, items: Vec::new() }); 208 name,
209 source_item_id,
210 items: Vec::new(),
211 });
203 self.process_module(Some(item), item_list); 212 self.process_module(Some(item), item_list);
204 self.push_item(current_module, RawItem::Module(item)); 213 self.push_item(current_module, RawItem::Module(item));
214 return;
205 } 215 }
216 tested_by!(name_res_works_for_broken_modules);
206 } 217 }
207 218
208 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { 219 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) {
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs
index a56dbaf90..742a19e5c 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs
@@ -15,7 +15,7 @@ fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc
15 } 15 }
16 let crate_id = db.crate_graph().iter().next().unwrap(); 16 let crate_id = db.crate_graph().iter().next().unwrap();
17 let krate = Crate { crate_id }; 17 let krate = Crate { crate_id };
18 collector::crate_def_map_query(&db, krate) 18 db.crate_def_map(krate)
19} 19}
20 20
21fn render_crate_def_map(map: &CrateDefMap) -> String { 21fn render_crate_def_map(map: &CrateDefMap) -> String {