@@ -17,7 +17,7 @@ use syntax::{
1717use crate :: {
1818 AssistId ,
1919 assist_context:: { AssistContext , Assists } ,
20- utils:: invert_boolean_expression_legacy,
20+ utils:: { invert_boolean_expression_legacy, is_never_block } ,
2121} ;
2222
2323// Assist: convert_to_guarded_return
@@ -54,9 +54,13 @@ fn if_expr_to_guarded_return(
5454 acc : & mut Assists ,
5555 ctx : & AssistContext < ' _ > ,
5656) -> Option < ( ) > {
57- if if_expr. else_branch ( ) . is_some ( ) {
58- return None ;
59- }
57+ let else_block = match if_expr. else_branch ( ) {
58+ Some ( ast:: ElseBranch :: Block ( block_expr) ) if is_never_block ( & ctx. sema , & block_expr) => {
59+ Some ( block_expr)
60+ }
61+ Some ( _) => return None ,
62+ _ => None ,
63+ } ;
6064
6165 let cond = if_expr. condition ( ) ?;
6266
@@ -96,7 +100,11 @@ fn if_expr_to_guarded_return(
96100
97101 let parent_container = parent_block. syntax ( ) . parent ( ) ?;
98102
99- let early_expression: ast:: Expr = early_expression ( parent_container, & ctx. sema ) ?;
103+ let early_expression = else_block
104+ . or_else ( || {
105+ early_expression ( parent_container, & ctx. sema ) . map ( ast:: make:: tail_only_block_expr)
106+ } ) ?
107+ . reset_indent ( ) ;
100108
101109 then_block. syntax ( ) . first_child_or_token ( ) . map ( |t| t. kind ( ) == T ! [ '{' ] ) ?;
102110
@@ -123,21 +131,14 @@ fn if_expr_to_guarded_return(
123131 && let ( Some ( pat) , Some ( expr) ) = ( let_expr. pat ( ) , let_expr. expr ( ) )
124132 {
125133 // If-let.
126- let let_else_stmt = make:: let_else_stmt (
127- pat,
128- None ,
129- expr,
130- ast:: make:: tail_only_block_expr ( early_expression. clone ( ) ) ,
131- ) ;
134+ let let_else_stmt =
135+ make:: let_else_stmt ( pat, None , expr, early_expression. clone ( ) ) ;
132136 let let_else_stmt = let_else_stmt. indent ( if_indent_level) ;
133137 let_else_stmt. syntax ( ) . clone ( )
134138 } else {
135139 // If.
136140 let new_expr = {
137- let then_branch = make:: block_expr (
138- once ( make:: expr_stmt ( early_expression. clone ( ) ) . into ( ) ) ,
139- None ,
140- ) ;
141+ let then_branch = clean_stmt_block ( & early_expression) ;
141142 let cond = invert_boolean_expression_legacy ( expr) ;
142143 make:: expr_if ( cond, then_branch, None ) . indent ( if_indent_level)
143144 } ;
@@ -272,6 +273,17 @@ fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
272273 chains
273274}
274275
276+ fn clean_stmt_block ( block : & ast:: BlockExpr ) -> ast:: BlockExpr {
277+ if block. statements ( ) . next ( ) . is_none ( )
278+ && let Some ( tail_expr) = block. tail_expr ( )
279+ && block. modifier ( ) . is_none ( )
280+ {
281+ make:: block_expr ( once ( make:: expr_stmt ( tail_expr) . into ( ) ) , None )
282+ } else {
283+ block. clone ( )
284+ }
285+ }
286+
275287#[ cfg( test) ]
276288mod tests {
277289 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -421,6 +433,53 @@ fn main() {
421433 ) ;
422434 }
423435
436+ #[ test]
437+ fn convert_if_let_has_never_type_else_block ( ) {
438+ check_assist (
439+ convert_to_guarded_return,
440+ r#"
441+ fn main() {
442+ if$0 let Ok(x) = Err(92) {
443+ foo(x);
444+ } else {
445+ // needless comment
446+ return;
447+ }
448+ }
449+ "# ,
450+ r#"
451+ fn main() {
452+ let Ok(x) = Err(92) else {
453+ // needless comment
454+ return;
455+ };
456+ foo(x);
457+ }
458+ "# ,
459+ ) ;
460+
461+ check_assist (
462+ convert_to_guarded_return,
463+ r#"
464+ fn main() {
465+ if$0 let Ok(x) = Err(92) {
466+ foo(x);
467+ } else {
468+ return
469+ }
470+ }
471+ "# ,
472+ r#"
473+ fn main() {
474+ let Ok(x) = Err(92) else {
475+ return
476+ };
477+ foo(x);
478+ }
479+ "# ,
480+ ) ;
481+ }
482+
424483 #[ test]
425484 fn convert_if_let_result_inside_let ( ) {
426485 check_assist (
0 commit comments