Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 21f4ff0

Browse files
ShoyuVanilladavidsemakula
authored andcommitted
Check for let expr ancestors instead of tail expr
1 parent d14b228 commit 21f4ff0

File tree

2 files changed

+29
-33
lines changed

2 files changed

+29
-33
lines changed

crates/hir-ty/src/diagnostics/expr.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use hir_expand::name;
1212
use itertools::Itertools;
1313
use rustc_hash::FxHashSet;
1414
use rustc_pattern_analysis::usefulness::{compute_match_usefulness, ValidityConstraint};
15+
use syntax::{ast, AstNode};
1516
use tracing::debug;
1617
use triomphe::Arc;
1718
use typed_arena::Arena;
@@ -108,7 +109,7 @@ impl ExprValidator {
108109
self.check_for_trailing_return(*body_expr, &body);
109110
}
110111
Expr::If { .. } => {
111-
self.check_for_unnecessary_else(id, expr, &body);
112+
self.check_for_unnecessary_else(id, expr, db);
112113
}
113114
Expr::Block { .. } => {
114115
self.validate_block(db, expr);
@@ -336,31 +337,34 @@ impl ExprValidator {
336337
}
337338
}
338339

339-
fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, body: &Body) {
340+
fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, db: &dyn HirDatabase) {
340341
if let Expr::If { condition: _, then_branch, else_branch } = expr {
341-
if let Some(else_branch) = else_branch {
342-
// If else branch has a tail, it is an "expression" that produces a value,
343-
// e.g. `let a = if { ... } else { ... };` and this `else` is not unnecessary
344-
let mut branch = *else_branch;
345-
loop {
346-
match body.exprs[branch] {
347-
Expr::Block { tail: Some(_), .. } => return,
348-
Expr::If { then_branch, else_branch, .. } => {
349-
if let Expr::Block { tail: Some(_), .. } = body.exprs[then_branch] {
350-
return;
351-
}
352-
if let Some(else_branch) = else_branch {
353-
// Continue checking for branches like `if { ... } else if { ... } else...`
354-
branch = else_branch;
355-
continue;
356-
}
357-
}
358-
_ => break,
359-
}
360-
break;
361-
}
362-
} else {
342+
if else_branch.is_none() {
343+
return;
344+
}
345+
let (body, source_map) = db.body_with_source_map(self.owner);
346+
let Ok(source_ptr) = source_map.expr_syntax(id) else {
363347
return;
348+
};
349+
let root = source_ptr.file_syntax(db.upcast());
350+
let ast::Expr::IfExpr(if_expr) = source_ptr.value.to_node(&root) else {
351+
return;
352+
};
353+
let mut top_if_expr = if_expr;
354+
loop {
355+
let parent = top_if_expr.syntax().parent();
356+
let has_parent_let_stmt =
357+
parent.as_ref().map_or(false, |node| ast::LetStmt::can_cast(node.kind()));
358+
if has_parent_let_stmt {
359+
// Bail if parent or direct ancestor is a let stmt.
360+
return;
361+
}
362+
let Some(parent_if_expr) = parent.and_then(ast::IfExpr::cast) else {
363+
// Parent is neither an if expr nor a let stmt.
364+
break;
365+
};
366+
// Check parent if expr.
367+
top_if_expr = parent_if_expr;
364368
}
365369
if let Expr::Block { statements, tail, .. } = &body.exprs[*then_branch] {
366370
let last_then_expr = tail.or_else(|| match statements.last()? {

crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,7 @@ fn test1(a: bool) {
400400
};
401401
}
402402
403-
fn test2(a: bool) -> i32 {
404-
if a {
405-
return 1;
406-
} else {
407-
0
408-
}
409-
}
410-
411-
fn test3(a: bool, b: bool, c: bool) {
403+
fn test2(a: bool, b: bool, c: bool) {
412404
let _x = if a {
413405
return;
414406
} else if b {

0 commit comments

Comments
 (0)