@@ -109,7 +109,7 @@ impl ExprValidator {
109
109
self . check_for_trailing_return ( * body_expr, & body) ;
110
110
}
111
111
Expr :: If { .. } => {
112
- self . check_for_unnecessary_else ( id, expr, db) ;
112
+ self . check_for_unnecessary_else ( id, expr, & body , db) ;
113
113
}
114
114
Expr :: Block { .. } => {
115
115
self . validate_block ( db, expr) ;
@@ -337,35 +337,17 @@ impl ExprValidator {
337
337
}
338
338
}
339
339
340
- fn check_for_unnecessary_else ( & mut self , id : ExprId , expr : & Expr , db : & dyn HirDatabase ) {
340
+ fn check_for_unnecessary_else (
341
+ & mut self ,
342
+ id : ExprId ,
343
+ expr : & Expr ,
344
+ body : & Body ,
345
+ db : & dyn HirDatabase ,
346
+ ) {
341
347
if let Expr :: If { condition : _, then_branch, else_branch } = expr {
342
348
if else_branch. is_none ( ) {
343
349
return ;
344
350
}
345
- let ( body, source_map) = db. body_with_source_map ( self . owner ) ;
346
- let Ok ( source_ptr) = source_map. expr_syntax ( id) else {
347
- 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;
368
- }
369
351
if let Expr :: Block { statements, tail, .. } = & body. exprs [ * then_branch] {
370
352
let last_then_expr = tail. or_else ( || match statements. last ( ) ? {
371
353
Statement :: Expr { expr, .. } => Some ( * expr) ,
@@ -374,6 +356,36 @@ impl ExprValidator {
374
356
if let Some ( last_then_expr) = last_then_expr {
375
357
let last_then_expr_ty = & self . infer [ last_then_expr] ;
376
358
if last_then_expr_ty. is_never ( ) {
359
+ // Only look at sources if the then branch diverges and we have an else branch.
360
+ let ( _, source_map) = db. body_with_source_map ( self . owner ) ;
361
+ let Ok ( source_ptr) = source_map. expr_syntax ( id) else {
362
+ return ;
363
+ } ;
364
+ let root = source_ptr. file_syntax ( db. upcast ( ) ) ;
365
+ let ast:: Expr :: IfExpr ( if_expr) = source_ptr. value . to_node ( & root) else {
366
+ return ;
367
+ } ;
368
+ let mut top_if_expr = if_expr;
369
+ loop {
370
+ let parent = top_if_expr. syntax ( ) . parent ( ) ;
371
+ let has_parent_expr_stmt_or_stmt_list =
372
+ parent. as_ref ( ) . map_or ( false , |node| {
373
+ ast:: ExprStmt :: can_cast ( node. kind ( ) )
374
+ | ast:: StmtList :: can_cast ( node. kind ( ) )
375
+ } ) ;
376
+ if has_parent_expr_stmt_or_stmt_list {
377
+ // Only emit diagnostic if parent or direct ancestor is either
378
+ // an expr stmt or a stmt list.
379
+ break ;
380
+ }
381
+ let Some ( parent_if_expr) = parent. and_then ( ast:: IfExpr :: cast) else {
382
+ // Bail if parent is neither an if expr, an expr stmt nor a stmt list.
383
+ return ;
384
+ } ;
385
+ // Check parent if expr.
386
+ top_if_expr = parent_if_expr;
387
+ }
388
+
377
389
self . diagnostics
378
390
. push ( BodyValidationDiagnostic :: RemoveUnnecessaryElse { if_expr : id } )
379
391
}
0 commit comments