pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
    match expr {
        ast::Expr::BlockExpr(b) => {
            if let Some(e) = b.tail_expr() {
                for_each_tail_expr(&e, cb);
            }
        }
        ast::Expr::EffectExpr(e) => match e.effect() {
            ast::Effect::Label(label) => {
                for_each_break_expr(Some(label), e.block_expr(), &mut |b| {
                    cb(&ast::Expr::BreakExpr(b))
                });
                if let Some(b) = e.block_expr() {
                    for_each_tail_expr(&ast::Expr::BlockExpr(b), cb);
                }
            }
            ast::Effect::Unsafe(_) => {
                if let Some(e) = e.block_expr().and_then(|b| b.tail_expr()) {
                    for_each_tail_expr(&e, cb);
                }
            }
            ast::Effect::Async(_) | ast::Effect::Try(_) | ast::Effect::Const(_) => cb(expr),
        },
        ast::Expr::IfExpr(if_) => {
            let mut if_ = if_.clone();
            loop {
                if let Some(block) = if_.then_branch() {
                    for_each_tail_expr(&ast::Expr::BlockExpr(block), cb);
                }
                match if_.else_branch() {
                    Some(ast::ElseBranch::IfExpr(it)) => if_ = it,
                    Some(ast::ElseBranch::Block(block)) => {
                        for_each_tail_expr(&ast::Expr::BlockExpr(block), cb);
                        break;
                    }
                    None => break,
                }
            }
        }
        ast::Expr::LoopExpr(l) => {
            for_each_break_expr(l.label(), l.loop_body(), &mut |b| cb(&ast::Expr::BreakExpr(b)))
        }
        ast::Expr::MatchExpr(m) => {
            if let Some(arms) = m.match_arm_list() {
                arms.arms().filter_map(|arm| arm.expr()).for_each(|e| for_each_tail_expr(&e, cb));
            }
        }
        ast::Expr::ArrayExpr(_)
        | ast::Expr::AwaitExpr(_)
        | ast::Expr::BinExpr(_)
        | ast::Expr::BoxExpr(_)
        | ast::Expr::BreakExpr(_)
        | ast::Expr::CallExpr(_)
        | ast::Expr::CastExpr(_)
        | ast::Expr::ClosureExpr(_)
        | ast::Expr::ContinueExpr(_)
        | ast::Expr::FieldExpr(_)
        | ast::Expr::ForExpr(_)
        | ast::Expr::IndexExpr(_)
        | ast::Expr::Literal(_)
        | ast::Expr::MacroCall(_)
        | ast::Expr::MacroStmts(_)
        | ast::Expr::MethodCallExpr(_)
        | ast::Expr::ParenExpr(_)
        | ast::Expr::PathExpr(_)
        | ast::Expr::PrefixExpr(_)
        | ast::Expr::RangeExpr(_)
        | ast::Expr::RecordExpr(_)
        | ast::Expr::RefExpr(_)
        | ast::Expr::ReturnExpr(_)
        | ast::Expr::TryExpr(_)
        | ast::Expr::TupleExpr(_)
        | ast::Expr::WhileExpr(_)
        | ast::Expr::YieldExpr(_) => cb(expr),
    }
}
/// Calls `cb` on each expression inside `expr` that is at "tail position".
/// Does not walk into `break` or `return` expressions.
/// Note that modifying the tree while iterating it will cause undefined iteration which might
/// potentially results in an out of bounds panic.
Calls `cb` on each expression inside `expr` that is at "tail position".
Does not walk into `break` or `return` expressions.
Note that modifying the tree while iterating it will cause undefined iteration which might
potentially results in an out of bounds panic.
Calls ` cb ` on each expression inside ` expr ` that is at " tail position " . Does not walk into ` break ` or ` return ` expressions . Note that modifying the tree while iterating it will cause undefined iteration which might potentially results in an out of bounds panic .
pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
    match expr {
        ast::Expr::BlockExpr(b) => {
            if let Some(e) = b.tail_expr() {
                for_each_tail_expr(&e, cb);
            }
        }
        ast::Expr::EffectExpr(e) => match e.effect() {
            ast::Effect::Label(label) => {
                for_each_break_expr(Some(label), e.block_expr(), &mut |b| {
                    cb(&ast::Expr::BreakExpr(b))
                });
                if let Some(b) = e.block_expr() {
                    for_each_tail_expr(&ast::Expr::BlockExpr(b), cb);
                }
            }
            ast::Effect::Unsafe(_) => {
                if let Some(e) = e.block_expr().and_then(|b| b.tail_expr()) {
                    for_each_tail_expr(&e, cb);
                }
            }
            ast::Effect::Async(_) | ast::Effect::Try(_) | ast::Effect::Const(_) => cb(expr),
        },
        ast::Expr::IfExpr(if_) => {
            let mut if_ = if_.clone();
            loop {
                if let Some(block) = if_.then_branch() {
                    for_each_tail_expr(&ast::Expr::BlockExpr(block), cb);
                }
                match if_.else_branch() {
                    Some(ast::ElseBranch::IfExpr(it)) => if_ = it,
                    Some(ast::ElseBranch::Block(block)) => {
                        for_each_tail_expr(&ast::Expr::BlockExpr(block), cb);
                        break;
                    }
                    None => break,
                }
            }
        }
        ast::Expr::LoopExpr(l) => {
            for_each_break_expr(l.label(), l.loop_body(), &mut |b| cb(&ast::Expr::BreakExpr(b)))
        }
        ast::Expr::MatchExpr(m) => {
            if let Some(arms) = m.match_arm_list() {
                arms.arms().filter_map(|arm| arm.expr()).for_each(|e| for_each_tail_expr(&e, cb));
            }
        }
        ast::Expr::ArrayExpr(_)
        | ast::Expr::AwaitExpr(_)
        | ast::Expr::BinExpr(_)
        | ast::Expr::BoxExpr(_)
        | ast::Expr::BreakExpr(_)
        | ast::Expr::CallExpr(_)
        | ast::Expr::CastExpr(_)
        | ast::Expr::ClosureExpr(_)
        | ast::Expr::ContinueExpr(_)
        | ast::Expr::FieldExpr(_)
        | ast::Expr::ForExpr(_)
        | ast::Expr::IndexExpr(_)
        | ast::Expr::Literal(_)
        | ast::Expr::MacroCall(_)
        | ast::Expr::MacroStmts(_)
        | ast::Expr::MethodCallExpr(_)
        | ast::Expr::ParenExpr(_)
        | ast::Expr::PathExpr(_)
        | ast::Expr::PrefixExpr(_)
        | ast::Expr::RangeExpr(_)
        | ast::Expr::RecordExpr(_)
        | ast::Expr::RefExpr(_)
        | ast::Expr::ReturnExpr(_)
        | ast::Expr::TryExpr(_)
        | ast::Expr::TupleExpr(_)
        | ast::Expr::WhileExpr(_)
        | ast::Expr::YieldExpr(_) => cb(expr),
    }
}
pub fn for_each_tail_expr ( expr : & ast :: Expr , cb : & mut dyn FnMut ( & ast :: Expr ) ) { match expr { ast :: Expr :: BlockExpr ( b ) => { if let Some ( e ) = b . tail_expr ( ) { for_each_tail_expr ( & e , cb ) ; } } ast :: Expr :: EffectExpr ( e ) => match e . effect ( ) { ast :: Effect :: Label ( label ) => { for_each_break_expr ( Some ( label ) , e . block_expr ( ) , & mut | b | { cb ( & ast :: Expr :: BreakExpr ( b ) ) } ) ; if let Some ( b ) = e . block_expr ( ) { for_each_tail_expr ( & ast :: Expr :: BlockExpr ( b ) , cb ) ; } } ast :: Effect :: Unsafe ( _ ) => { if let Some ( e ) = e . block_expr ( ) . and_then ( | b | b . tail_expr ( ) ) { for_each_tail_expr ( & e , cb ) ; } } ast :: Effect :: Async ( _ ) | ast :: Effect :: Try ( _ ) | ast :: Effect :: Const ( _ ) => cb ( expr ) , } , ast :: Expr :: IfExpr ( if_ ) => { let mut if_ = if_ . clone ( ) ; loop { if let Some ( block ) = if_ . then_branch ( ) { for_each_tail_expr ( & ast :: Expr :: BlockExpr ( block ) , cb ) ; } match if_ . else_branch ( ) { Some ( ast :: ElseBranch :: IfExpr ( it ) ) => if_ = it , Some ( ast :: ElseBranch :: Block ( block ) ) => { for_each_tail_expr ( & ast :: Expr :: BlockExpr ( block ) , cb ) ; break ; } None => break , } } } ast :: Expr :: LoopExpr ( l ) => { for_each_break_expr ( l . label ( ) , l . loop_body ( ) , & mut | b | cb ( & ast :: Expr :: BreakExpr ( b ) ) ) } ast :: Expr :: MatchExpr ( m ) => { if let Some ( arms ) = m . match_arm_list ( ) { arms . arms ( ) . filter_map ( | arm | arm . expr ( ) ) . for_each ( | e | for_each_tail_expr ( & e , cb ) ) ; } } ast :: Expr :: ArrayExpr ( _ ) | ast :: Expr :: AwaitExpr ( _ ) | ast :: Expr :: BinExpr ( _ ) | ast :: Expr :: BoxExpr ( _ ) | ast :: Expr :: BreakExpr ( _ ) | ast :: Expr :: CallExpr ( _ ) | ast :: Expr :: CastExpr ( _ ) | ast :: Expr :: ClosureExpr ( _ ) | ast :: Expr :: ContinueExpr ( _ ) | ast :: Expr :: FieldExpr ( _ ) | ast :: Expr :: ForExpr ( _ ) | ast :: Expr :: IndexExpr ( _ ) | ast :: Expr :: Literal ( _ ) | ast :: Expr :: MacroCall ( _ ) | ast :: Expr :: MacroStmts ( _ ) | ast :: Expr :: MethodCallExpr ( _ ) | ast :: Expr :: ParenExpr ( _ ) | ast :: Expr :: PathExpr ( _ ) | ast :: Expr :: PrefixExpr ( _ ) | ast :: Expr :: RangeExpr ( _ ) | ast :: Expr :: RecordExpr ( _ ) | ast :: Expr :: RefExpr ( _ ) | ast :: Expr :: ReturnExpr ( _ ) | ast :: Expr :: TryExpr ( _ ) | ast :: Expr :: TupleExpr ( _ ) | ast :: Expr :: WhileExpr ( _ ) | ast :: Expr :: YieldExpr ( _ ) => cb ( expr ) , } }
Calls `cb` on each expression inside `expr` that is at "tail position".
Calls ` cb ` on each expression inside ` expr ` that is at " tail position " .
expr
&ast::Expr
cb
&mut dyn FnMut(&ast::Expr)