Skip to content

Commit f322977

Browse files
committed
Only allocate item blocks if they actually contain items or statement macros
1 parent 9fb997f commit f322977

1 file changed

Lines changed: 52 additions & 18 deletions

File tree

crates/span/src/ast_id.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ impl ErasedFileAstId {
206206
self.0 >> (HASH_BITS + INDEX_BITS)
207207
}
208208

209+
#[inline]
210+
pub fn is_root(self) -> bool {
211+
self.kind() == ErasedFileAstIdKind::Root as u32
212+
}
213+
209214
fn ast_id_for(
210215
node: &SyntaxNode,
211216
index_map: &mut ErasedAstIdNextIndexMap,
@@ -220,14 +225,16 @@ impl ErasedFileAstId {
220225
.or_else(|| asm_expr_ast_id(node, index_map))
221226
}
222227

223-
fn should_alloc(node: &SyntaxNode) -> bool {
228+
fn should_alloc(node: &SyntaxNode) -> Option<ErasedFileAstIdKind> {
224229
let kind = node.kind();
225230
should_alloc_has_name(kind)
226-
|| should_alloc_assoc_item(kind)
227-
|| ast::ExternBlock::can_cast(kind)
228-
|| ast::Use::can_cast(kind)
229-
|| ast::Impl::can_cast(kind)
230-
|| ast::AsmExpr::can_cast(kind)
231+
.or_else(|| should_alloc_assoc_item(kind))
232+
.or_else(|| {
233+
ast::ExternBlock::can_cast(kind).then_some(ErasedFileAstIdKind::ExternBlock)
234+
})
235+
.or_else(|| ast::Use::can_cast(kind).then_some(ErasedFileAstIdKind::Use))
236+
.or_else(|| ast::Impl::can_cast(kind).then_some(ErasedFileAstIdKind::Impl))
237+
.or_else(|| ast::AsmExpr::can_cast(kind).then_some(ErasedFileAstIdKind::AsmExpr))
231238
}
232239

233240
#[inline]
@@ -478,8 +485,8 @@ macro_rules! register_has_name_ast_id {
478485
}
479486
}
480487

481-
fn should_alloc_has_name(kind: SyntaxKind) -> bool {
482-
false $( || ast::$ident::can_cast(kind) )*
488+
fn should_alloc_has_name(kind: SyntaxKind) -> Option<ErasedFileAstIdKind> {
489+
$( if ast::$ident::can_cast(kind) { Some(ErasedFileAstIdKind::$ident) } else )* { None }
483490
}
484491
};
485492
}
@@ -528,8 +535,8 @@ macro_rules! register_assoc_item_ast_id {
528535
}
529536
}
530537

531-
fn should_alloc_assoc_item(kind: SyntaxKind) -> bool {
532-
false $( || ast::$ident::can_cast(kind) )*
538+
fn should_alloc_assoc_item(kind: SyntaxKind) -> Option<ErasedFileAstIdKind> {
539+
$( if ast::$ident::can_cast(kind) { Some(ErasedFileAstIdKind::$ident) } else )* { None }
533540
}
534541
};
535542
}
@@ -612,22 +619,49 @@ impl AstIdMap {
612619
syntax::WalkEvent::Enter(node) => {
613620
if ast::BlockExpr::can_cast(node.kind()) {
614621
blocks.push((node, ContainsItems::No));
615-
} else if ErasedFileAstId::should_alloc(&node) {
622+
} else if let Some(kind) = ErasedFileAstId::should_alloc(&node) {
616623
// Allocate blocks on-demand, only if they have items.
617624
// We don't associate items with blocks, only with items, since block IDs can be quite unstable.
618625
// FIXME: Is this the correct thing to do? Macro calls might actually be more incremental if
619626
// associated with blocks (not sure). Either way it's not a big deal.
627+
let is_item = matches!(
628+
kind,
629+
ErasedFileAstIdKind::Enum
630+
| ErasedFileAstIdKind::Struct
631+
| ErasedFileAstIdKind::Union
632+
| ErasedFileAstIdKind::ExternCrate
633+
| ErasedFileAstIdKind::MacroDef
634+
| ErasedFileAstIdKind::MacroRules
635+
| ErasedFileAstIdKind::Module
636+
| ErasedFileAstIdKind::Static
637+
| ErasedFileAstIdKind::Trait
638+
| ErasedFileAstIdKind::Const
639+
| ErasedFileAstIdKind::Fn
640+
| ErasedFileAstIdKind::TypeAlias
641+
| ErasedFileAstIdKind::ExternBlock
642+
| ErasedFileAstIdKind::Use
643+
| ErasedFileAstIdKind::Impl
644+
);
620645
if let Some((
621646
last_block_node,
622647
already_allocated @ ContainsItems::No,
623648
)) = blocks.last_mut()
649+
&& (is_item
650+
|| (kind == ErasedFileAstIdKind::MacroCall && {
651+
let mut anc = node.ancestors();
652+
_ = anc.next();
653+
anc.next().is_some_and(|it| {
654+
it.kind() == SyntaxKind::MACRO_EXPR
655+
}) && anc.next().is_some_and(|it| {
656+
it.kind() == SyntaxKind::EXPR_STMT
657+
|| it.kind() == SyntaxKind::STMT_LIST
658+
})
659+
}))
624660
{
625-
let block_ast_id = block_expr_ast_id(
626-
last_block_node,
627-
&mut index_map,
628-
parent_of(parent_idx, &res),
629-
)
630-
.expect("not a BlockExpr");
661+
let parent = parent_of(parent_idx, &res);
662+
let block_ast_id =
663+
block_expr_ast_id(last_block_node, &mut index_map, parent)
664+
.expect("not a BlockExpr");
631665
res.arena
632666
.alloc((SyntaxNodePtr::new(last_block_node), block_ast_id));
633667
*already_allocated = ContainsItems::Yes;
@@ -644,7 +678,7 @@ impl AstIdMap {
644678
}
645679
}
646680
syntax::WalkEvent::Leave(node) => {
647-
if ast::BlockExpr::can_cast(node.kind()) {
681+
if cfg!(debug_assertions) && ast::BlockExpr::can_cast(node.kind()) {
648682
assert_eq!(
649683
blocks.pop().map(|it| it.0),
650684
Some(node),

0 commit comments

Comments
 (0)