Unnamed repository; edit this file 'description' to name the repository.
internal: Only intern blocks that declare items
Lukas Wirth 2023-03-26
parent 0daf069 · commit 675fc88
-rw-r--r--crates/hir-def/src/body/lower.rs21
-rw-r--r--crates/hir-def/src/body/scope.rs9
-rw-r--r--crates/hir-def/src/expr.rs8
-rw-r--r--crates/hir-def/src/item_tree.rs8
-rw-r--r--crates/hir-def/src/item_tree/lower.rs28
5 files changed, 57 insertions, 17 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index a93fcb3b1d..3fb3e4f68d 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -37,6 +37,7 @@ use crate::{
RecordFieldPat, RecordLitField, Statement,
},
item_scope::BuiltinShadowMode,
+ item_tree::ItemTree,
lang_item::LangItem,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
@@ -888,16 +889,24 @@ impl ExprCollector<'_> {
fn collect_block_(
&mut self,
block: ast::BlockExpr,
- mk_block: impl FnOnce(BlockId, Box<[Statement]>, Option<ExprId>) -> Expr,
+ mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr,
) -> ExprId {
let file_local_id = self.ast_id_map.ast_id(&block);
let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
- let block_loc =
- BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
- let block_id = self.db.intern_block(block_loc);
- let (module, def_map) = match self.db.block_def_map(block_id) {
- Some(def_map) => {
+ let block_id = if ItemTree::block_has_items(self.db, ast_id.file_id, &block) {
+ Some(self.db.intern_block(BlockLoc {
+ ast_id,
+ module: self.expander.def_map.module_id(self.expander.module),
+ }))
+ } else {
+ None
+ };
+
+ let (module, def_map) = match block_id
+ .and_then(|block_id| self.db.block_def_map(block_id).zip(Some(block_id)))
+ {
+ Some((def_map, block_id)) => {
self.body.block_scopes.push(block_id);
(def_map.root(), def_map)
}
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs
index 8ddb89a472..8fe20da747 100644
--- a/crates/hir-def/src/body/scope.rs
+++ b/crates/hir-def/src/body/scope.rs
@@ -115,15 +115,10 @@ impl ExprScopes {
fn new_block_scope(
&mut self,
parent: ScopeId,
- block: BlockId,
+ block: Option<BlockId>,
label: Option<(LabelId, Name)>,
) -> ScopeId {
- self.scopes.alloc(ScopeData {
- parent: Some(parent),
- block: Some(block),
- label,
- entries: vec![],
- })
+ self.scopes.alloc(ScopeData { parent: Some(parent), block, label, entries: vec![] })
}
fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 7ede19cc3c..443594d271 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -117,23 +117,23 @@ pub enum Expr {
expr: ExprId,
},
Block {
- id: BlockId,
+ id: Option<BlockId>,
statements: Box<[Statement]>,
tail: Option<ExprId>,
label: Option<LabelId>,
},
Async {
- id: BlockId,
+ id: Option<BlockId>,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Const {
- id: BlockId,
+ id: Option<BlockId>,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Unsafe {
- id: BlockId,
+ id: Option<BlockId>,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 9da5b2d47c..0694217017 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -152,6 +152,14 @@ impl ItemTree {
&self.top_level
}
+ pub fn block_has_items(
+ db: &dyn DefDatabase,
+ file_id: HirFileId,
+ block: &ast::BlockExpr,
+ ) -> bool {
+ lower::Ctx::new(db, file_id).block_has_items(block)
+ }
+
/// Returns the inner attributes of the source file.
pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
Attrs::filter(
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 77b186f8e3..49deff080e 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -101,6 +101,34 @@ impl<'a> Ctx<'a> {
self.tree
}
+ pub(super) fn block_has_items(mut self, block: &ast::BlockExpr) -> bool {
+ let statement_has_item = block
+ .statements()
+ .find_map(|stmt| match stmt {
+ ast::Stmt::Item(item) => self.lower_mod_item(&item),
+ // Macro calls can be both items and expressions. The syntax library always treats
+ // them as expressions here, so we undo that.
+ ast::Stmt::ExprStmt(es) => match es.expr()? {
+ ast::Expr::MacroExpr(expr) => self.lower_mod_item(&expr.macro_call()?.into()),
+ _ => None,
+ },
+ _ => None,
+ })
+ .is_some();
+ if statement_has_item {
+ return true;
+ }
+
+ if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() {
+ if let Some(call) = expr.macro_call() {
+ if let Some(_) = self.lower_mod_item(&call.into()) {
+ return true;
+ }
+ }
+ }
+ false
+ }
+
fn data(&mut self) -> &mut ItemTreeData {
self.tree.data_mut()
}