@@ -109,7 +109,7 @@ impl ExprValidator {
109109 self . check_for_trailing_return ( * body_expr, & body) ;
110110 }
111111 Expr :: If { .. } => {
112- self . check_for_unnecessary_else ( id, expr, db) ;
112+ self . check_for_unnecessary_else ( id, expr, & body , db) ;
113113 }
114114 Expr :: Block { .. } => {
115115 self . validate_block ( db, expr) ;
@@ -337,35 +337,17 @@ impl ExprValidator {
337337 }
338338 }
339339
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+ ) {
341347 if let Expr :: If { condition : _, then_branch, else_branch } = expr {
342348 if else_branch. is_none ( ) {
343349 return ;
344350 }
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- }
369351 if let Expr :: Block { statements, tail, .. } = & body. exprs [ * then_branch] {
370352 let last_then_expr = tail. or_else ( || match statements. last ( ) ? {
371353 Statement :: Expr { expr, .. } => Some ( * expr) ,
@@ -374,6 +356,36 @@ impl ExprValidator {
374356 if let Some ( last_then_expr) = last_then_expr {
375357 let last_then_expr_ty = & self . infer [ last_then_expr] ;
376358 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+
377389 self . diagnostics
378390 . push ( BodyValidationDiagnostic :: RemoveUnnecessaryElse { if_expr : id } )
379391 }
0 commit comments