use crate::ast::*;
pub fn stmt_definitely_exits(stmt: &SNode) -> bool {
match &stmt.node {
Node::ReturnStmt { .. } | Node::ThrowStmt { .. } | Node::BreakStmt | Node::ContinueStmt => {
true
}
Node::IfElse {
then_body,
else_body: Some(else_body),
..
} => block_definitely_exits(then_body) && block_definitely_exits(else_body),
Node::MatchExpr { arms, .. } => match_definitely_exits(arms),
Node::Block(body)
| Node::TryExpr { body }
| Node::CostRoute { body, .. }
| Node::MutexBlock { body }
| Node::DeadlineBlock { body, .. }
| Node::Retry { body, .. } => block_definitely_exits(body),
Node::TryCatch {
body,
catch_body,
finally_body,
..
} => {
finally_body
.as_ref()
.is_some_and(|body| block_definitely_exits(body))
|| (block_definitely_exits(body) && block_definitely_exits(catch_body))
}
_ => false,
}
}
fn match_definitely_exits(arms: &[MatchArm]) -> bool {
if arms.is_empty() {
return false;
}
let has_unguarded_wildcard = arms.iter().any(|arm| {
arm.guard.is_none() && matches!(&arm.pattern.node, Node::Identifier(name) if name == "_")
});
has_unguarded_wildcard && arms.iter().all(|arm| block_definitely_exits(&arm.body))
}
pub fn block_definitely_exits(stmts: &[SNode]) -> bool {
stmts.iter().any(stmt_definitely_exits)
}