diff --git a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index ae13f83fbc34..2a0ed4dc9e92 100644 --- a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -75,8 +75,8 @@ fn if_expr_to_guarded_return( let let_chains = flat_let_chain(cond); - let then_block = if_expr.then_branch()?; - let then_block = then_block.stmt_list()?; + let then_branch = if_expr.then_branch()?; + let then_block = then_branch.stmt_list()?; let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?; @@ -84,17 +84,8 @@ fn if_expr_to_guarded_return( return None; } - // FIXME: This relies on untyped syntax tree and casts to much. It should be - // rewritten to use strongly-typed APIs. - // check for early return and continue - let first_in_then_block = then_block.syntax().first_child()?; - if ast::ReturnExpr::can_cast(first_in_then_block.kind()) - || ast::ContinueExpr::can_cast(first_in_then_block.kind()) - || first_in_then_block - .children() - .any(|x| ast::ReturnExpr::can_cast(x.kind()) || ast::ContinueExpr::can_cast(x.kind())) - { + if is_early_block(&then_block) || is_never_block(&ctx.sema, &then_branch) { return None; } @@ -284,6 +275,17 @@ fn clean_stmt_block(block: &ast::BlockExpr) -> ast::BlockExpr { } } +fn is_early_block(then_block: &ast::StmtList) -> bool { + let is_early_expr = + |expr| matches!(expr, ast::Expr::ReturnExpr(_) | ast::Expr::ContinueExpr(_)); + let into_expr = |stmt| match stmt { + ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(), + _ => None, + }; + then_block.tail_expr().is_some_and(is_early_expr) + || then_block.statements().filter_map(into_expr).any(is_early_expr) +} + #[cfg(test)] mod tests { use crate::tests::{check_assist, check_assist_not_applicable};