@@ -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