Skip to content

Commit 21f4ff0

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

2 files changed

Lines changed: 29 additions & 33 deletions

File tree

‎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-
fncheck_for_unnecessary_else(&mutself,id:ExprId,expr:&Expr,body:&Body){
340+
fncheck_for_unnecessary_else(&mutself,id:ExprId,expr:&Expr,db:&dynHirDatabase){
340341
ifletExpr::If{condition: _, then_branch, else_branch } = expr {
341-
ifletSome(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-
letmut branch = *else_branch;
345-
loop{
346-
match body.exprs[branch]{
347-
Expr::Block{tail:Some(_), .. } => return,
348-
Expr::If{ then_branch, else_branch, .. } => {
349-
ifletExpr::Block{tail:Some(_), .. } = body.exprs[then_branch]{
350-
return;
351-
}
352-
ifletSome(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+
letOk(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+
letmut 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+
letSome(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
ifletExpr::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)