@@ -189,10 +189,7 @@ impl GotoRewriter<'_> {
189189
190190 fn recurse_into_inner_goto_block ( & mut self , mac : & mut syn:: Macro ) -> bool {
191191 if mac. path . is_ident ( "switch" ) || mac. path . is_ident ( "goto_block" ) {
192- if let Ok ( mut inner) = syn:: parse2 :: < Expr > ( mac. tokens . clone ( ) ) {
193- self . visit_expr_mut ( & mut inner) ;
194- mac. tokens = quote ! ( #inner) ;
195- }
192+ visit_control_flow_macro ( self , mac, true ) ;
196193 return true ;
197194 }
198195 false
@@ -284,12 +281,47 @@ impl StateMachine for SwitchStateMachine {
284281 }
285282}
286283
284+ // Macro tokens are opaque to syn's normal traversal. A nested goto block is
285+ // transparent to exits; a nested switch owns breaks in its arms, but not in
286+ // its condition or guards. Neither macro owns continues.
287+ fn visit_control_flow_macro (
288+ visitor : & mut impl VisitMut ,
289+ mac : & mut syn:: Macro ,
290+ visit_switch_arms : bool ,
291+ ) {
292+ let Some ( name) = mac. path . segments . last ( ) . map ( |s| & s. ident ) else {
293+ return ;
294+ } ;
295+ if name == "goto_block"
296+ && let Ok ( mut body) = syn:: parse2 :: < Expr > ( mac. tokens . clone ( ) )
297+ {
298+ visitor. visit_expr_mut ( & mut body) ;
299+ mac. tokens = quote ! ( #body) ;
300+ } else if name == "switch"
301+ && let Ok ( mut body) = syn:: parse2 :: < syn:: ExprMatch > ( mac. tokens . clone ( ) )
302+ {
303+ visitor. visit_expr_mut ( & mut body. expr ) ;
304+ for arm in & mut body. arms {
305+ if let Some ( ( _, guard) ) = & mut arm. guard {
306+ visitor. visit_expr_mut ( guard) ;
307+ }
308+ if visit_switch_arms {
309+ visitor. visit_expr_mut ( & mut arm. body ) ;
310+ }
311+ }
312+ mac. tokens = quote ! ( #body) ;
313+ }
314+ }
315+
287316// Rewrite break into break '__sm
288317struct ExitSwitchRewriter {
289318 label : Lifetime ,
290319}
291320
292321impl VisitMut for ExitSwitchRewriter {
322+ fn visit_macro_mut ( & mut self , mac : & mut syn:: Macro ) {
323+ visit_control_flow_macro ( self , mac, false ) ;
324+ }
293325 fn visit_expr_break_mut ( & mut self , node : & mut ExprBreak ) {
294326 if node. label . is_none ( ) {
295327 node. label = Some ( self . label . clone ( ) ) ;
@@ -333,6 +365,9 @@ impl PropagateRewriter {
333365}
334366
335367impl VisitMut for PropagateRewriter {
368+ fn visit_macro_mut ( & mut self , mac : & mut syn:: Macro ) {
369+ visit_control_flow_macro ( self , mac, matches ! ( self . kind, ControlKind :: Continue ) ) ;
370+ }
336371 fn visit_expr_mut ( & mut self , expr : & mut Expr ) {
337372 let hit = match self . kind {
338373 ControlKind :: Break => {
0 commit comments