@@ -550,20 +550,6 @@ impl ExprCollector<'_> {
550550 None => self . alloc_expr ( Expr :: Missing , syntax_ptr) ,
551551 }
552552 }
553- ast:: Expr :: MacroStmts ( e) => {
554- let statements: Box < [ _ ] > =
555- e. statements ( ) . filter_map ( |s| self . collect_stmt ( s) ) . collect ( ) ;
556- let tail = e. expr ( ) . map ( |e| self . collect_expr ( e) ) ;
557-
558- if e. syntax ( ) . children ( ) . next ( ) . is_none ( ) {
559- // HACK: make sure that macros that expand to nothing aren't treated as a `()`
560- // expression when used in block tail position.
561- cov_mark:: hit!( empty_macro_in_trailing_position_is_removed) ;
562- return None ;
563- }
564-
565- self . alloc_expr ( Expr :: MacroStmts { tail, statements } , syntax_ptr)
566- }
567553 ast:: Expr :: UnderscoreExpr ( _) => self . alloc_expr ( Expr :: Underscore , syntax_ptr) ,
568554 } )
569555 }
@@ -640,7 +626,58 @@ impl ExprCollector<'_> {
640626 }
641627 }
642628
643- fn collect_stmt ( & mut self , s : ast:: Stmt ) -> Option < Statement > {
629+ fn collect_macro_as_stmt (
630+ & mut self ,
631+ mac : ast:: MacroExpr ,
632+ ) -> Option < ( Vec < Statement > , Option < ExprId > ) > {
633+ let mac_call = mac. macro_call ( ) ?;
634+ let syntax_ptr = AstPtr :: new ( & ast:: Expr :: from ( mac) ) ;
635+ let macro_ptr = AstPtr :: new ( & mac_call) ;
636+ let expansion = self . collect_macro_call (
637+ mac_call,
638+ macro_ptr,
639+ false ,
640+ |this, expansion : Option < ast:: MacroStmts > | match expansion {
641+ Some ( expansion) => {
642+ let mut statements: Vec < _ > = expansion
643+ . statements ( )
644+ . filter_map ( |stmt| this. collect_stmt ( stmt) )
645+ . flatten ( )
646+ . collect ( ) ;
647+ let tail = expansion. expr ( ) . and_then ( |expr| match expr {
648+ ast:: Expr :: MacroExpr ( mac) => {
649+ let ( stmts, tail) = this. collect_macro_as_stmt ( mac) ?;
650+ statements. extend ( stmts) ;
651+ tail
652+ }
653+ expr => Some ( this. collect_expr ( expr) ) ,
654+ } ) ;
655+ Some ( ( statements, tail) )
656+ }
657+ None => None ,
658+ } ,
659+ ) ;
660+ let mut stmts = Vec :: new ( ) ;
661+ let expr = match expansion {
662+ Some ( ( statements, tail) ) => {
663+ stmts. extend ( statements) ;
664+ // Make the macro-call point to its expanded expression so we can query
665+ // semantics on syntax pointers to the macro
666+ let src = self . expander . to_source ( syntax_ptr) ;
667+ match tail {
668+ Some ( tail) => {
669+ self . source_map . expr_map . insert ( src, tail) ;
670+ tail
671+ }
672+ None => self . make_expr ( Expr :: Missing , Ok ( src. clone ( ) ) ) ,
673+ }
674+ }
675+ None => self . alloc_expr ( Expr :: Missing , syntax_ptr) ,
676+ } ;
677+ Some ( ( stmts, Some ( expr) ) )
678+ }
679+
680+ fn collect_stmt ( & mut self , s : ast:: Stmt ) -> Option < Vec < Statement > > {
644681 match s {
645682 ast:: Stmt :: LetStmt ( stmt) => {
646683 if self . check_cfg ( & stmt) . is_none ( ) {
@@ -654,7 +691,7 @@ impl ExprCollector<'_> {
654691 . let_else ( )
655692 . and_then ( |let_else| let_else. block_expr ( ) )
656693 . map ( |block| self . collect_block ( block) ) ;
657- Some ( Statement :: Let { pat, type_ref, initializer, else_branch } )
694+ Some ( vec ! [ Statement :: Let { pat, type_ref, initializer, else_branch } ] )
658695 }
659696 ast:: Stmt :: ExprStmt ( stmt) => {
660697 let expr = stmt. expr ( ) ;
@@ -665,47 +702,15 @@ impl ExprCollector<'_> {
665702 }
666703 let has_semi = stmt. semicolon_token ( ) . is_some ( ) ;
667704 // Note that macro could be expanded to multiple statements
668- if let Some ( expr @ ast:: Expr :: MacroExpr ( mac) ) = & expr {
669- let mac_call = mac. macro_call ( ) ?;
670- let syntax_ptr = AstPtr :: new ( expr) ;
671- let macro_ptr = AstPtr :: new ( & mac_call) ;
672- let stmt = self . collect_macro_call (
673- mac_call,
674- macro_ptr,
675- false ,
676- |this, expansion : Option < ast:: MacroStmts > | match expansion {
677- Some ( expansion) => {
678- let statements = expansion
679- . statements ( )
680- . filter_map ( |stmt| this. collect_stmt ( stmt) )
681- . collect ( ) ;
682- let tail = expansion. expr ( ) . map ( |expr| this. collect_expr ( expr) ) ;
683-
684- let mac_stmts = this. alloc_expr (
685- Expr :: MacroStmts { tail, statements } ,
686- AstPtr :: new ( & ast:: Expr :: MacroStmts ( expansion) ) ,
687- ) ;
688-
689- Some ( mac_stmts)
690- }
691- None => None ,
692- } ,
693- ) ;
694-
695- let expr = match stmt {
696- Some ( expr) => {
697- // Make the macro-call point to its expanded expression so we can query
698- // semantics on syntax pointers to the macro
699- let src = self . expander . to_source ( syntax_ptr) ;
700- self . source_map . expr_map . insert ( src, expr) ;
701- expr
702- }
703- None => self . alloc_expr ( Expr :: Missing , syntax_ptr) ,
704- } ;
705- Some ( Statement :: Expr { expr, has_semi } )
705+ if let Some ( ast:: Expr :: MacroExpr ( mac) ) = expr {
706+ let ( mut statements, tail) = self . collect_macro_as_stmt ( mac) ?;
707+ if let Some ( expr) = tail {
708+ statements. push ( Statement :: Expr { expr, has_semi } ) ;
709+ }
710+ Some ( statements)
706711 } else {
707712 let expr = self . collect_expr_opt ( expr) ;
708- Some ( Statement :: Expr { expr, has_semi } )
713+ Some ( vec ! [ Statement :: Expr { expr, has_semi } ] )
709714 }
710715 }
711716 ast:: Stmt :: Item ( _item) => None ,
@@ -730,8 +735,15 @@ impl ExprCollector<'_> {
730735 let prev_local_module = mem:: replace ( & mut self . expander . module , module) ;
731736
732737 let mut statements: Vec < _ > =
733- block. statements ( ) . filter_map ( |s| self . collect_stmt ( s) ) . collect ( ) ;
734- let tail = block. tail_expr ( ) . and_then ( |e| self . maybe_collect_expr ( e) ) ;
738+ block. statements ( ) . filter_map ( |s| self . collect_stmt ( s) ) . flatten ( ) . collect ( ) ;
739+ let tail = block. tail_expr ( ) . and_then ( |e| match e {
740+ ast:: Expr :: MacroExpr ( mac) => {
741+ let ( stmts, tail) = self . collect_macro_as_stmt ( mac) ?;
742+ statements. extend ( stmts) ;
743+ tail
744+ }
745+ expr => self . maybe_collect_expr ( expr) ,
746+ } ) ;
735747 let tail = tail. or_else ( || {
736748 let stmt = statements. pop ( ) ?;
737749 if let Statement :: Expr { expr, has_semi : false } = stmt {
0 commit comments