From da57f5dc17303cfd5ba318d1735c7f325f6b7130 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 1 Feb 2021 13:32:43 +0100 Subject: Shortcut `block_def_map` if there's no inner items This previously didn't work, but apparently only because of the wonky test setup --- crates/hir_def/src/body/lower.rs | 9 ++++++--- crates/hir_def/src/body/tests.rs | 4 ++-- crates/hir_def/src/db.rs | 2 +- crates/hir_def/src/lib.rs | 9 ++++++++- crates/hir_def/src/nameres.rs | 13 +++++++++---- 5 files changed, 26 insertions(+), 11 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bc61730a7..540c6c9ad 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -700,10 +700,13 @@ impl ExprCollector<'_> { let ast_id = self.expander.ast_id(&block); let block_loc = BlockLoc { ast_id, module: self.expander.module }; let block_id = self.db.intern_block(block_loc); - let def_map = self.db.block_def_map(block_id); - let root = def_map.module_id(def_map.root()); + let opt_def_map = self.db.block_def_map(block_id); + let has_def_map = opt_def_map.is_some(); + let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); + let module = + if has_def_map { def_map.module_id(def_map.root()) } else { self.expander.module }; let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); - let prev_module = mem::replace(&mut self.expander.module, root); + let prev_module = mem::replace(&mut self.expander.module, module); self.collect_stmts_items(block.statements()); let statements = diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index da60072ce..404603360 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs @@ -43,7 +43,7 @@ fn block_def_map_at(ra_fixture: &str) -> Arc { let mut block = block_at_pos(&db, &def_map, position).expect("couldn't find enclosing function or block"); loop { - let def_map = db.block_def_map(block); + let def_map = db.block_def_map(block).unwrap_or_else(|| def_map.clone()); let new_block = block_at_pos(&db, &def_map, position); match new_block { Some(new_block) => { @@ -58,6 +58,7 @@ fn block_def_map_at(ra_fixture: &str) -> Arc { } fn block_at_pos(db: &dyn DefDatabase, def_map: &DefMap, position: FilePosition) -> Option { + // Find the smallest (innermost) function containing the cursor. let mut size = None; let mut fn_def = None; for (_, module) in def_map.modules() { @@ -73,7 +74,6 @@ fn block_at_pos(db: &dyn DefDatabase, def_map: &DefMap, position: FilePosition) let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root); let range = ast.syntax().text_range(); - // Find the smallest (innermost) function containing the cursor. if !range.contains(position.offset) { continue; } diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index aef7e1f6c..7fe6f6346 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -59,7 +59,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { fn crate_def_map_query(&self, krate: CrateId) -> Arc; #[salsa::invoke(DefMap::block_def_map_query)] - fn block_def_map(&self, block: BlockId) -> Arc; + fn block_def_map(&self, block: BlockId) -> Option>; #[salsa::invoke(StructData::struct_data_query)] fn struct_data(&self, id: StructId) -> Arc; diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 42b50b5b7..5dd3705b0 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -81,7 +81,13 @@ pub struct ModuleId { impl ModuleId { pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc { match self.block { - Some(block) => db.block_def_map(block), + Some(block) => { + db.block_def_map(block).unwrap_or_else(|| { + // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s, + // so the `DefMap` here must exist. + panic!("no `block_def_map` for `ModuleId` {:?}", self); + }) + } None => db.crate_def_map(self.krate), } } @@ -239,6 +245,7 @@ pub struct BlockId(salsa::InternId); #[derive(Debug, Hash, PartialEq, Eq, Clone)] pub struct BlockLoc { ast_id: AstId, + /// The containing module. module: ModuleId, } impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 0a15fc470..ece5958f4 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -197,12 +197,17 @@ impl DefMap { Arc::new(def_map) } - pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc { + pub(crate) fn block_def_map_query( + db: &dyn DefDatabase, + block_id: BlockId, + ) -> Option> { let block: BlockLoc = db.lookup_intern_block(block_id); let parent = block.module.def_map(db); - // FIXME: It would be good to just return the parent map when the block has no items, but - // we rely on `def_map.block` in a few places, which is `Some` for the inner `DefMap`. + let item_tree = db.item_tree(block.ast_id.file_id); + if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { + return None; + } let block_info = BlockInfo { block: block_id, parent, parent_module: block.module.local_id }; @@ -211,7 +216,7 @@ impl DefMap { def_map.block = Some(block_info); let def_map = collector::collect_defs(db, def_map, Some(block.ast_id)); - Arc::new(def_map) + Some(Arc::new(def_map)) } fn empty(krate: CrateId, edition: Edition) -> DefMap { -- cgit v1.2.3