@@ -435,6 +435,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
435
435
Annotatable :: ImplItem ( item) => {
436
436
Annotatable :: ImplItem ( item. map ( |item| cfg. fold_impl_item ( item) . pop ( ) . unwrap ( ) ) )
437
437
}
438
+ Annotatable :: Stmt ( stmt) => {
439
+ Annotatable :: Stmt ( stmt. map ( |stmt| cfg. fold_stmt ( stmt) . pop ( ) . unwrap ( ) ) )
440
+ }
441
+ Annotatable :: Expr ( expr) => {
442
+ Annotatable :: Expr ( cfg. fold_expr ( expr) )
443
+ }
438
444
}
439
445
}
440
446
@@ -503,6 +509,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
503
509
Annotatable :: Item ( item) => token:: NtItem ( item) ,
504
510
Annotatable :: TraitItem ( item) => token:: NtTraitItem ( item. into_inner ( ) ) ,
505
511
Annotatable :: ImplItem ( item) => token:: NtImplItem ( item. into_inner ( ) ) ,
512
+ Annotatable :: Stmt ( stmt) => token:: NtStmt ( stmt. into_inner ( ) ) ,
513
+ Annotatable :: Expr ( expr) => token:: NtExpr ( expr) ,
506
514
} ) ) . into ( ) ;
507
515
let tok_result = mac. expand ( self . cx , attr. span , attr. tokens , item_tok) ;
508
516
self . parse_expansion ( tok_result, kind, & attr. path , attr. span )
@@ -751,6 +759,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
751
759
Some ( expansion)
752
760
}
753
761
Err ( mut err) => {
762
+ err. set_span ( span) ;
754
763
err. emit ( ) ;
755
764
self . cx . trace_macros_diag ( ) ;
756
765
kind. dummy ( span)
@@ -796,7 +805,13 @@ impl<'a> Parser<'a> {
796
805
Expansion :: Stmts ( stmts)
797
806
}
798
807
ExpansionKind :: Expr => Expansion :: Expr ( self . parse_expr ( ) ?) ,
799
- ExpansionKind :: OptExpr => Expansion :: OptExpr ( Some ( self . parse_expr ( ) ?) ) ,
808
+ ExpansionKind :: OptExpr => {
809
+ if self . token != token:: Eof {
810
+ Expansion :: OptExpr ( Some ( self . parse_expr ( ) ?) )
811
+ } else {
812
+ Expansion :: OptExpr ( None )
813
+ }
814
+ } ,
800
815
ExpansionKind :: Ty => Expansion :: Ty ( self . parse_ty ( ) ?) ,
801
816
ExpansionKind :: Pat => Expansion :: Pat ( self . parse_pat ( ) ?) ,
802
817
} )
@@ -904,6 +919,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
904
919
let mut expr = self . cfg . configure_expr ( expr) . into_inner ( ) ;
905
920
expr. node = self . cfg . configure_expr_kind ( expr. node ) ;
906
921
922
+ let ( attr, derives, expr) = self . classify_item ( expr) ;
923
+
924
+ if attr. is_some ( ) || !derives. is_empty ( ) {
925
+ // collect the invoc regardless of whether or not attributes are permitted here
926
+ // expansion will eat the attribute so it won't error later
927
+ attr. as_ref ( ) . map ( |a| self . cfg . maybe_emit_expr_attr_err ( a) ) ;
928
+
929
+ // ExpansionKind::Expr requires the macro to emit an expression
930
+ return self . collect_attr ( attr, derives, Annotatable :: Expr ( P ( expr) ) , ExpansionKind :: Expr )
931
+ . make_expr ( ) ;
932
+ }
933
+
907
934
if let ast:: ExprKind :: Mac ( mac) = expr. node {
908
935
self . check_attributes ( & expr. attrs ) ;
909
936
self . collect_bang ( mac, expr. span , ExpansionKind :: Expr ) . make_expr ( )
@@ -916,6 +943,16 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
916
943
let mut expr = configure ! ( self , expr) . into_inner ( ) ;
917
944
expr. node = self . cfg . configure_expr_kind ( expr. node ) ;
918
945
946
+ let ( attr, derives, expr) = self . classify_item ( expr) ;
947
+
948
+ if attr. is_some ( ) || !derives. is_empty ( ) {
949
+ attr. as_ref ( ) . map ( |a| self . cfg . maybe_emit_expr_attr_err ( a) ) ;
950
+
951
+ return self . collect_attr ( attr, derives, Annotatable :: Expr ( P ( expr) ) ,
952
+ ExpansionKind :: OptExpr )
953
+ . make_opt_expr ( ) ;
954
+ }
955
+
919
956
if let ast:: ExprKind :: Mac ( mac) = expr. node {
920
957
self . check_attributes ( & expr. attrs ) ;
921
958
self . collect_bang ( mac, expr. span , ExpansionKind :: OptExpr ) . make_opt_expr ( )
@@ -938,33 +975,47 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
938
975
}
939
976
940
977
fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVector < ast:: Stmt > {
941
- let stmt = match self . cfg . configure_stmt ( stmt) {
978
+ let mut stmt = match self . cfg . configure_stmt ( stmt) {
942
979
Some ( stmt) => stmt,
943
980
None => return SmallVector :: new ( ) ,
944
981
} ;
945
982
946
- let ( mac , style , attrs ) = if let StmtKind :: Mac ( mac ) = stmt . node {
947
- mac . into_inner ( )
948
- } else {
949
- // The placeholder expander gives ids to statements, so we avoid folding the id here.
950
- let ast :: Stmt { id , node , span } = stmt ;
951
- return noop_fold_stmt_kind ( node , self ) . into_iter ( ) . map ( |node| {
952
- ast :: Stmt { id : id , node : node , span : span }
953
- } ) . collect ( )
954
- } ;
983
+ // we'll expand attributes on expressions separately
984
+ if !stmt . is_expr ( ) {
985
+ let ( attr , derives , stmt_ ) = self . classify_item ( stmt ) ;
986
+
987
+ if attr . is_some ( ) || !derives . is_empty ( ) {
988
+ return self . collect_attr ( attr , derives ,
989
+ Annotatable :: Stmt ( P ( stmt_ ) ) , ExpansionKind :: Stmts )
990
+ . make_stmts ( ) ;
991
+ }
955
992
956
- self . check_attributes ( & attrs ) ;
957
- let mut placeholder = self . collect_bang ( mac , stmt . span , ExpansionKind :: Stmts ) . make_stmts ( ) ;
993
+ stmt = stmt_ ;
994
+ }
958
995
959
- // If this is a macro invocation with a semicolon, then apply that
960
- // semicolon to the final statement produced by expansion.
961
- if style == MacStmtStyle :: Semicolon {
962
- if let Some ( stmt) = placeholder. pop ( ) {
963
- placeholder. push ( stmt. add_trailing_semicolon ( ) ) ;
996
+ if let StmtKind :: Mac ( mac) = stmt. node {
997
+ let ( mac, style, attrs) = mac. into_inner ( ) ;
998
+ self . check_attributes ( & attrs) ;
999
+ let mut placeholder = self . collect_bang ( mac, stmt. span , ExpansionKind :: Stmts )
1000
+ . make_stmts ( ) ;
1001
+
1002
+ // If this is a macro invocation with a semicolon, then apply that
1003
+ // semicolon to the final statement produced by expansion.
1004
+ if style == MacStmtStyle :: Semicolon {
1005
+ if let Some ( stmt) = placeholder. pop ( ) {
1006
+ placeholder. push ( stmt. add_trailing_semicolon ( ) ) ;
1007
+ }
964
1008
}
1009
+
1010
+ return placeholder;
965
1011
}
966
1012
967
- placeholder
1013
+ // The placeholder expander gives ids to statements, so we avoid folding the id here.
1014
+ let ast:: Stmt { id, node, span } = stmt;
1015
+ noop_fold_stmt_kind ( node, self ) . into_iter ( ) . map ( |node| {
1016
+ ast:: Stmt { id, node, span }
1017
+ } ) . collect ( )
1018
+
968
1019
}
969
1020
970
1021
fn fold_block ( & mut self , block : P < Block > ) -> P < Block > {
0 commit comments