about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-03-25 20:44:12 +0100
committerLukas Wirth <lukastw97@gmail.com>2023-03-25 20:44:12 +0100
commit675fc88afd9f4bb767330eac554672ae9764cd0c (patch)
tree4b6f7a7fb9c84ad5291df04043b048027a12188e
parent0daf069b0efb7690bcd3436318e806b8b4d983a4 (diff)
downloadrust-675fc88afd9f4bb767330eac554672ae9764cd0c.tar.gz
rust-675fc88afd9f4bb767330eac554672ae9764cd0c.zip
internal: Only intern blocks that declare items
-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 a93fcb3b1dc..3fb3e4f68dd 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 8ddb89a4725..8fe20da7477 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 7ede19cc3c2..443594d2717 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 9da5b2d47c8..06942170179 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 77b186f8e3f..49deff080e5 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()
     }