Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e5b23e3

Browse files
committed
Derive block attributes from block item tree
1 parent 05b0612 commit e5b23e3

File tree

8 files changed

+41
-27
lines changed

8 files changed

+41
-27
lines changed

crates/hir-def/src/attr.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -431,12 +431,10 @@ impl AttrsWithOwner {
431431
.item_tree(db)
432432
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
433433
.clone(),
434-
ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
435-
db.upcast(),
436-
InFile::new(block.file_id, block.to_node(db.upcast()))
437-
.as_ref()
438-
.map(|it| it as &dyn ast::HasAttrs),
439-
),
434+
ModuleOrigin::BlockExpr { id, block } => {
435+
let tree = db.block_item_tree_query(id);
436+
tree.raw_attrs(AttrOwner::TopLevel).clone()
437+
}
440438
}
441439
}
442440
AttrDefId::FieldId(it) => {

crates/hir-def/src/body/lower.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,9 @@ impl ExprCollector<'_> {
11001100
ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))),
11011101
_ => false,
11021102
});
1103-
statement_has_item || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
1103+
statement_has_item
1104+
|| matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
1105+
|| (block.may_carry_attributes() && block.attrs().next().is_some())
11041106
};
11051107

11061108
let block_id = if block_has_items {

crates/hir-def/src/db.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
8282
#[salsa::invoke(ItemTree::file_item_tree_query)]
8383
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
8484

85+
#[salsa::invoke(ItemTree::block_item_tree_query)]
86+
// FIXME: Investigate memory usage increase if this were not transparent
87+
// Also make sure to `shrink_to_fit` if you do
88+
#[salsa::transparent]
89+
fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
90+
8591
#[salsa::invoke(crate_def_map_wait)]
8692
#[salsa::transparent]
8793
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;

crates/hir-def/src/item_tree.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ impl ItemTree {
143143
Arc::new(item_tree)
144144
}
145145

146+
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
147+
let loc = db.lookup_intern_block(block);
148+
let block = loc.ast_id.to_node(db.upcast());
149+
150+
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
151+
Arc::new(ctx.lower_block(&block))
152+
}
153+
146154
/// Returns an iterator over all items located at the top level of the `HirFileId` this
147155
/// `ItemTree` was created from.
148156
pub fn top_level_items(&self) -> &[ModItem] {
@@ -178,13 +186,6 @@ impl ItemTree {
178186
self.data.get_or_insert_with(Box::default)
179187
}
180188

181-
fn block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
182-
let loc = db.lookup_intern_block(block);
183-
let block = loc.ast_id.to_node(db.upcast());
184-
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
185-
Arc::new(ctx.lower_block(&block))
186-
}
187-
188189
fn shrink_to_fit(&mut self) {
189190
if let Some(data) = &mut self.data {
190191
let ItemTreeData {
@@ -382,7 +383,7 @@ impl TreeId {
382383

383384
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
384385
match self.block {
385-
Some(block) => ItemTree::block_item_tree(db, block),
386+
Some(block) => ItemTree::block_item_tree_query(db, block),
386387
None => db.file_item_tree(self.file),
387388
}
388389
}

crates/hir-def/src/item_tree/lower.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ impl<'a> Ctx<'a> {
7777
}
7878

7979
pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree {
80+
self.tree
81+
.attrs
82+
.insert(AttrOwner::TopLevel, RawAttrs::new(self.db.upcast(), block, self.hygiene()));
8083
self.tree.top_level = block
8184
.statements()
8285
.filter_map(|stmt| match stmt {

crates/hir-def/src/nameres.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ pub enum ModuleOrigin {
227227
},
228228
/// Pseudo-module introduced by a block scope (contains only inner items).
229229
BlockExpr {
230+
id: BlockId,
230231
block: AstId<ast::BlockExpr>,
231232
},
232233
}
@@ -269,7 +270,7 @@ impl ModuleOrigin {
269270
definition.file_id,
270271
ModuleSource::Module(definition.to_node(db.upcast())),
271272
),
272-
ModuleOrigin::BlockExpr { block } => {
273+
ModuleOrigin::BlockExpr { block, .. } => {
273274
InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
274275
}
275276
}
@@ -325,8 +326,10 @@ impl DefMap {
325326
// modules declared by blocks with items. At the moment, we don't use
326327
// this visibility for anything outside IDE, so that's probably OK.
327328
let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
328-
let module_data =
329-
ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
329+
let module_data = ModuleData::new(
330+
ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
331+
visibility,
332+
);
330333

331334
let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
332335
def_map.data = parent_map.data.clone();
@@ -643,7 +646,7 @@ impl ModuleData {
643646
definition.into()
644647
}
645648
ModuleOrigin::Inline { definition, .. } => definition.file_id,
646-
ModuleOrigin::BlockExpr { block } => block.file_id,
649+
ModuleOrigin::BlockExpr { block, .. } => block.file_id,
647650
}
648651
}
649652

crates/hir-expand/src/attrs.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,7 @@ fn inner_attributes(
342342
ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
343343
ast::Module(it) => it.item_list()?.syntax().clone(),
344344
ast::BlockExpr(it) => {
345-
use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
346-
// Block expressions accept outer and inner attributes, but only when they are the outer
347-
// expression of an expression statement or the final expression of another block expression.
348-
let may_carry_attributes = matches!(
349-
it.syntax().parent().map(|it| it.kind()),
350-
Some(BLOCK_EXPR | EXPR_STMT)
351-
);
352-
if !may_carry_attributes {
345+
if !it.may_carry_attributes() {
353346
return None
354347
}
355348
syntax.clone()

crates/syntax/src/ast/node_ext.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ impl ast::BlockExpr {
6161
pub fn tail_expr(&self) -> Option<ast::Expr> {
6262
self.stmt_list()?.tail_expr()
6363
}
64+
/// Block expressions accept outer and inner attributes, but only when they are the outer
65+
/// expression of an expression statement or the final expression of another block expression.
66+
pub fn may_carry_attributes(&self) -> bool {
67+
matches!(
68+
self.syntax().parent().map(|it| it.kind()),
69+
Some(SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT)
70+
)
71+
}
6472
}
6573

6674
#[derive(Debug, PartialEq, Eq, Clone)]

0 commit comments

Comments
 (0)