aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-02-04 12:44:54 +0000
committerJonas Schievink <[email protected]>2021-02-04 12:44:54 +0000
commit26a2a2433c7bae1533d07a38a6003e6f40fa97d9 (patch)
treec1a3bbed8832b554c6991802f728d99ea6ced088 /crates/hir_def/src
parent01bc1fdff8b04d373e794af29b18243eb9d15e34 (diff)
Don't keep the parent DefMap alive via Arc
This seems like it could easily leak a lot of memory since we don't currently run GC
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/body/tests.rs7
-rw-r--r--crates/hir_def/src/nameres.rs60
-rw-r--r--crates/hir_def/src/nameres/collector.rs9
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs14
-rw-r--r--crates/hir_def/src/nameres/tests.rs13
5 files changed, 67 insertions, 36 deletions
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index 404603360..a92134ba7 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -34,7 +34,7 @@ fn check_diagnostics(ra_fixture: &str) {
34 db.check_diagnostics(); 34 db.check_diagnostics();
35} 35}
36 36
37fn block_def_map_at(ra_fixture: &str) -> Arc<DefMap> { 37fn block_def_map_at(ra_fixture: &str) -> String {
38 let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); 38 let (db, position) = crate::test_db::TestDB::with_position(ra_fixture);
39 39
40 let krate = db.crate_graph().iter().next().unwrap(); 40 let krate = db.crate_graph().iter().next().unwrap();
@@ -51,7 +51,7 @@ fn block_def_map_at(ra_fixture: &str) -> Arc<DefMap> {
51 block = new_block; 51 block = new_block;
52 } 52 }
53 None => { 53 None => {
54 return def_map; 54 return def_map.dump(&db);
55 } 55 }
56 } 56 }
57 } 57 }
@@ -138,8 +138,7 @@ fn block_at_pos(db: &dyn DefDatabase, def_map: &DefMap, position: FilePosition)
138} 138}
139 139
140fn check_at(ra_fixture: &str, expect: Expect) { 140fn check_at(ra_fixture: &str, expect: Expect) {
141 let def_map = block_def_map_at(ra_fixture); 141 let actual = block_def_map_at(ra_fixture);
142 let actual = def_map.dump();
143 expect.assert_eq(&actual); 142 expect.assert_eq(&actual);
144} 143}
145 144
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 68998c121..ad2e9bcac 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -100,11 +100,12 @@ pub struct DefMap {
100} 100}
101 101
102/// For `DefMap`s computed for a block expression, this stores its location in the parent map. 102/// For `DefMap`s computed for a block expression, this stores its location in the parent map.
103#[derive(Debug, PartialEq, Eq)] 103#[derive(Debug, PartialEq, Eq, Clone, Copy)]
104struct BlockInfo { 104struct BlockInfo {
105 /// The `BlockId` this `DefMap` was created from.
105 block: BlockId, 106 block: BlockId,
106 parent: Arc<DefMap>, 107 /// The containing module.
107 parent_module: LocalModuleId, 108 parent: ModuleId,
108} 109}
109 110
110impl std::ops::Index<LocalModuleId> for DefMap { 111impl std::ops::Index<LocalModuleId> for DefMap {
@@ -211,17 +212,16 @@ impl DefMap {
211 block_id: BlockId, 212 block_id: BlockId,
212 ) -> Option<Arc<DefMap>> { 213 ) -> Option<Arc<DefMap>> {
213 let block: BlockLoc = db.lookup_intern_block(block_id); 214 let block: BlockLoc = db.lookup_intern_block(block_id);
214 let parent = block.module.def_map(db);
215 215
216 let item_tree = db.item_tree(block.ast_id.file_id); 216 let item_tree = db.item_tree(block.ast_id.file_id);
217 if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { 217 if item_tree.inner_items_of_block(block.ast_id.value).is_empty() {
218 return None; 218 return None;
219 } 219 }
220 220
221 let block_info = 221 let block_info = BlockInfo { block: block_id, parent: block.module };
222 BlockInfo { block: block_id, parent, parent_module: block.module.local_id };
223 222
224 let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition); 223 let parent_map = block.module.def_map(db);
224 let mut def_map = DefMap::empty(block.module.krate, parent_map.edition);
225 def_map.block = Some(block_info); 225 def_map.block = Some(block_info);
226 226
227 let def_map = collector::collect_defs(db, def_map, Some(block.ast_id)); 227 let def_map = collector::collect_defs(db, def_map, Some(block.ast_id));
@@ -289,9 +289,15 @@ impl DefMap {
289 ModuleId { krate: self.krate, local_id, block } 289 ModuleId { krate: self.krate, local_id, block }
290 } 290 }
291 291
292 pub(crate) fn crate_root(&self) -> ModuleId { 292 pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId {
293 let (root_map, _) = self.ancestor_maps(self.root).last().unwrap(); 293 self.with_ancestor_maps(db, self.root, &mut |def_map, _module| {
294 root_map.module_id(root_map.root) 294 if def_map.block.is_none() {
295 Some(def_map.module_id(def_map.root))
296 } else {
297 None
298 }
299 })
300 .expect("DefMap chain without root")
295 } 301 }
296 302
297 pub(crate) fn resolve_path( 303 pub(crate) fn resolve_path(
@@ -306,26 +312,42 @@ impl DefMap {
306 (res.resolved_def, res.segment_index) 312 (res.resolved_def, res.segment_index)
307 } 313 }
308 314
309 /// Iterates over the containing `DefMap`s, if `self` is a `DefMap` corresponding to a block 315 /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
310 /// expression. 316 ///
311 fn ancestor_maps( 317 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
318 /// `None`, iteration continues.
319 fn with_ancestor_maps<T>(
312 &self, 320 &self,
321 db: &dyn DefDatabase,
313 local_mod: LocalModuleId, 322 local_mod: LocalModuleId,
314 ) -> impl Iterator<Item = (&DefMap, LocalModuleId)> { 323 f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
315 std::iter::successors(Some((self, local_mod)), |(map, _)| { 324 ) -> Option<T> {
316 map.block.as_ref().map(|block| (&*block.parent, block.parent_module)) 325 if let Some(it) = f(self, local_mod) {
317 }) 326 return Some(it);
327 }
328 let mut block = self.block;
329 while let Some(block_info) = block {
330 let parent = block_info.parent.def_map(db);
331 if let Some(it) = f(&parent, block_info.parent.local_id) {
332 return Some(it);
333 }
334 block = parent.block;
335 }
336
337 None
318 } 338 }
319 339
320 // FIXME: this can use some more human-readable format (ideally, an IR 340 // FIXME: this can use some more human-readable format (ideally, an IR
321 // even), as this should be a great debugging aid. 341 // even), as this should be a great debugging aid.
322 pub fn dump(&self) -> String { 342 pub fn dump(&self, db: &dyn DefDatabase) -> String {
323 let mut buf = String::new(); 343 let mut buf = String::new();
344 let mut arc;
324 let mut current_map = self; 345 let mut current_map = self;
325 while let Some(block) = &current_map.block { 346 while let Some(block) = &current_map.block {
326 go(&mut buf, current_map, "block scope", current_map.root); 347 go(&mut buf, current_map, "block scope", current_map.root);
327 buf.push('\n'); 348 buf.push('\n');
328 current_map = &*block.parent; 349 arc = block.parent.def_map(db);
350 current_map = &*arc;
329 } 351 }
330 go(&mut buf, current_map, "crate", current_map.root); 352 go(&mut buf, current_map, "crate", current_map.root);
331 return buf; 353 return buf;
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 6e86cc4a7..f904a97de 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1449,10 +1449,11 @@ impl ModCollector<'_, '_> {
1449 if let Some(macro_call_id) = 1449 if let Some(macro_call_id) =
1450 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1450 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
1451 path.as_ident().and_then(|name| { 1451 path.as_ident().and_then(|name| {
1452 self.def_collector 1452 self.def_collector.def_map.with_ancestor_maps(
1453 .def_map 1453 self.def_collector.db,
1454 .ancestor_maps(self.module_id) 1454 self.module_id,
1455 .find_map(|(map, module)| map[module].scope.get_legacy_macro(&name)) 1455 &mut |map, module| map[module].scope.get_legacy_macro(&name),
1456 )
1456 }) 1457 })
1457 }) 1458 })
1458 { 1459 {
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index ecf75c777..2a3ac5d7b 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -110,6 +110,7 @@ impl DefMap {
110 let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); 110 let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
111 result.segment_index = Some(usize::max_value()); 111 result.segment_index = Some(usize::max_value());
112 112
113 let mut arc;
113 let mut current_map = self; 114 let mut current_map = self;
114 loop { 115 loop {
115 let new = current_map.resolve_path_fp_with_macro_single( 116 let new = current_map.resolve_path_fp_with_macro_single(
@@ -131,8 +132,9 @@ impl DefMap {
131 132
132 match &current_map.block { 133 match &current_map.block {
133 Some(block) => { 134 Some(block) => {
134 current_map = &block.parent; 135 original_module = block.parent.local_id;
135 original_module = block.parent_module; 136 arc = block.parent.def_map(db);
137 current_map = &*arc;
136 } 138 }
137 None => return result, 139 None => return result,
138 } 140 }
@@ -152,7 +154,7 @@ impl DefMap {
152 PathKind::DollarCrate(krate) => { 154 PathKind::DollarCrate(krate) => {
153 if krate == self.krate { 155 if krate == self.krate {
154 mark::hit!(macro_dollar_crate_self); 156 mark::hit!(macro_dollar_crate_self);
155 PerNs::types(self.crate_root().into(), Visibility::Public) 157 PerNs::types(self.crate_root(db).into(), Visibility::Public)
156 } else { 158 } else {
157 let def_map = db.crate_def_map(krate); 159 let def_map = db.crate_def_map(krate);
158 let module = def_map.module_id(def_map.root); 160 let module = def_map.module_id(def_map.root);
@@ -160,7 +162,7 @@ impl DefMap {
160 PerNs::types(module.into(), Visibility::Public) 162 PerNs::types(module.into(), Visibility::Public)
161 } 163 }
162 } 164 }
163 PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), 165 PathKind::Crate => PerNs::types(self.crate_root(db).into(), Visibility::Public),
164 // plain import or absolute path in 2015: crate-relative with 166 // plain import or absolute path in 2015: crate-relative with
165 // fallback to extern prelude (with the simplification in 167 // fallback to extern prelude (with the simplification in
166 // rust-lang/rust#57745) 168 // rust-lang/rust#57745)
@@ -206,10 +208,10 @@ impl DefMap {
206 segments: path.segments.clone(), 208 segments: path.segments.clone(),
207 }; 209 };
208 log::debug!("`super` path: {} -> {} in parent map", path, new_path); 210 log::debug!("`super` path: {} -> {} in parent map", path, new_path);
209 return block.parent.resolve_path_fp_with_macro( 211 return block.parent.def_map(db).resolve_path_fp_with_macro(
210 db, 212 db,
211 mode, 213 mode,
212 block.parent_module, 214 block.parent.local_id,
213 &new_path, 215 &new_path,
214 shadow, 216 shadow,
215 ); 217 );
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index 723481c36..bd3e2701b 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -11,7 +11,9 @@ use base_db::{fixture::WithFixture, SourceDatabase};
11use expect_test::{expect, Expect}; 11use expect_test::{expect, Expect};
12use test_utils::mark; 12use test_utils::mark;
13 13
14use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 14use crate::{db::DefDatabase, test_db::TestDB};
15
16use super::DefMap;
15 17
16fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { 18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
17 let db = TestDB::with_files(ra_fixture); 19 let db = TestDB::with_files(ra_fixture);
@@ -19,9 +21,14 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
19 db.crate_def_map(krate) 21 db.crate_def_map(krate)
20} 22}
21 23
24fn render_crate_def_map(ra_fixture: &str) -> String {
25 let db = TestDB::with_files(ra_fixture);
26 let krate = db.crate_graph().iter().next().unwrap();
27 db.crate_def_map(krate).dump(&db)
28}
29
22fn check(ra_fixture: &str, expect: Expect) { 30fn check(ra_fixture: &str, expect: Expect) {
23 let def_map = compute_crate_def_map(ra_fixture); 31 let actual = render_crate_def_map(ra_fixture);
24 let actual = def_map.dump();
25 expect.assert_eq(&actual); 32 expect.assert_eq(&actual);
26} 33}
27 34