From 675fc88afd9f4bb767330eac554672ae9764cd0c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 25 Mar 2023 20:44:12 +0100 Subject: [PATCH] internal: Only intern blocks that declare items --- crates/hir-def/src/body/lower.rs | 21 ++++++++++++++------ crates/hir-def/src/body/scope.rs | 9 ++------- crates/hir-def/src/expr.rs | 8 ++++---- crates/hir-def/src/item_tree.rs | 8 ++++++++ crates/hir-def/src/item_tree/lower.rs | 28 +++++++++++++++++++++++++++ 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) -> Expr, + mk_block: impl FnOnce(Option, Box<[Statement]>, Option) -> 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, 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, statements: Box<[Statement]>, tail: Option, label: Option, }, Async { - id: BlockId, + id: Option, statements: Box<[Statement]>, tail: Option, }, Const { - id: BlockId, + id: Option, statements: Box<[Statement]>, tail: Option, }, Unsafe { - id: BlockId, + id: Option, statements: Box<[Statement]>, tail: Option, }, 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() }