@@ -550,20 +550,6 @@ impl ExprCollector<'_> {
550
550
None => self . alloc_expr ( Expr :: Missing , syntax_ptr) ,
551
551
}
552
552
}
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
- }
567
553
ast:: Expr :: UnderscoreExpr ( _) => self . alloc_expr ( Expr :: Underscore , syntax_ptr) ,
568
554
} )
569
555
}
@@ -640,7 +626,58 @@ impl ExprCollector<'_> {
640
626
}
641
627
}
642
628
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 > > {
644
681
match s {
645
682
ast:: Stmt :: LetStmt ( stmt) => {
646
683
if self . check_cfg ( & stmt) . is_none ( ) {
@@ -654,7 +691,7 @@ impl ExprCollector<'_> {
654
691
. let_else ( )
655
692
. and_then ( |let_else| let_else. block_expr ( ) )
656
693
. 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 } ] )
658
695
}
659
696
ast:: Stmt :: ExprStmt ( stmt) => {
660
697
let expr = stmt. expr ( ) ;
@@ -665,47 +702,15 @@ impl ExprCollector<'_> {
665
702
}
666
703
let has_semi = stmt. semicolon_token ( ) . is_some ( ) ;
667
704
// 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)
706
711
} else {
707
712
let expr = self . collect_expr_opt ( expr) ;
708
- Some ( Statement :: Expr { expr, has_semi } )
713
+ Some ( vec ! [ Statement :: Expr { expr, has_semi } ] )
709
714
}
710
715
}
711
716
ast:: Stmt :: Item ( _item) => None ,
@@ -730,8 +735,15 @@ impl ExprCollector<'_> {
730
735
let prev_local_module = mem:: replace ( & mut self . expander . module , module) ;
731
736
732
737
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
+ } ) ;
735
747
let tail = tail. or_else ( || {
736
748
let stmt = statements. pop ( ) ?;
737
749
if let Statement :: Expr { expr, has_semi : false } = stmt {
0 commit comments