@@ -435,6 +435,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
435435 Annotatable :: ImplItem ( item) => {
436436 Annotatable :: ImplItem ( item. map ( |item| cfg. fold_impl_item ( item) . pop ( ) . unwrap ( ) ) )
437437 }
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+ }
438444 }
439445 }
440446
@@ -503,6 +509,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
503509 Annotatable :: Item ( item) => token:: NtItem ( item) ,
504510 Annotatable :: TraitItem ( item) => token:: NtTraitItem ( item. into_inner ( ) ) ,
505511 Annotatable :: ImplItem ( item) => token:: NtImplItem ( item. into_inner ( ) ) ,
512+ Annotatable :: Stmt ( stmt) => token:: NtStmt ( stmt. into_inner ( ) ) ,
513+ Annotatable :: Expr ( expr) => token:: NtExpr ( expr) ,
506514 } ) ) . into ( ) ;
507515 let tok_result = mac. expand ( self . cx , attr. span , attr. tokens , item_tok) ;
508516 self . parse_expansion ( tok_result, kind, & attr. path , attr. span )
@@ -751,6 +759,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
751759 Some ( expansion)
752760 }
753761 Err ( mut err) => {
762+ err. set_span ( span) ;
754763 err. emit ( ) ;
755764 self . cx . trace_macros_diag ( ) ;
756765 kind. dummy ( span)
@@ -796,7 +805,13 @@ impl<'a> Parser<'a> {
796805 Expansion :: Stmts ( stmts)
797806 }
798807 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+ } ,
800815 ExpansionKind :: Ty => Expansion :: Ty ( self . parse_ty ( ) ?) ,
801816 ExpansionKind :: Pat => Expansion :: Pat ( self . parse_pat ( ) ?) ,
802817 } )
@@ -904,6 +919,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
904919 let mut expr = self . cfg . configure_expr ( expr) . into_inner ( ) ;
905920 expr. node = self . cfg . configure_expr_kind ( expr. node ) ;
906921
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+
907934 if let ast:: ExprKind :: Mac ( mac) = expr. node {
908935 self . check_attributes ( & expr. attrs ) ;
909936 self . collect_bang ( mac, expr. span , ExpansionKind :: Expr ) . make_expr ( )
@@ -916,6 +943,16 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
916943 let mut expr = configure ! ( self , expr) . into_inner ( ) ;
917944 expr. node = self . cfg . configure_expr_kind ( expr. node ) ;
918945
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+
919956 if let ast:: ExprKind :: Mac ( mac) = expr. node {
920957 self . check_attributes ( & expr. attrs ) ;
921958 self . collect_bang ( mac, expr. span , ExpansionKind :: OptExpr ) . make_opt_expr ( )
@@ -938,33 +975,47 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
938975 }
939976
940977 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) {
942979 Some ( stmt) => stmt,
943980 None => return SmallVector :: new ( ) ,
944981 } ;
945982
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+ }
955992
956- self . check_attributes ( & attrs ) ;
957- let mut placeholder = self . collect_bang ( mac , stmt . span , ExpansionKind :: Stmts ) . make_stmts ( ) ;
993+ stmt = stmt_ ;
994+ }
958995
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+ }
9641008 }
1009+
1010+ return placeholder;
9651011 }
9661012
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+
9681019 }
9691020
9701021 fn fold_block ( & mut self , block : P < Block > ) -> P < Block > {
0 commit comments