From 10ec0f885a33beeca47ec9ff4e6dc570d27085ba Mon Sep 17 00:00:00 2001 From: dfireBird Date: Thu, 20 Nov 2025 09:54:17 +0530 Subject: [PATCH] fix: consider let else block for variables and control flow --- .../src/handlers/extract_function.rs | 63 ++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index ef4b977fe524..9c8bf5ee001e 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -693,11 +693,17 @@ impl FunctionBody { parent .statements() .filter(|stmt| text_range.contains_range(stmt.syntax().text_range())) - .filter_map(|stmt| match stmt { - ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(), - ast::Stmt::Item(_) => None, - ast::Stmt::LetStmt(stmt) => stmt.initializer(), + .flat_map(|stmt| match stmt { + ast::Stmt::ExprStmt(expr_stmt) => vec![expr_stmt.expr()], + ast::Stmt::Item(_) => vec![None], + ast::Stmt::LetStmt(stmt) => vec![ + stmt.initializer(), + stmt.let_else() + .and_then(|le| le.block_expr()) + .map(|be| ast::Expr::BlockExpr(be)), + ], }) + .filter_map(std::convert::identity) .for_each(|expr| walk_expr(&expr, cb)); if let Some(expr) = parent .tail_expr() @@ -716,11 +722,17 @@ impl FunctionBody { parent .statements() .filter(|stmt| text_range.contains_range(stmt.syntax().text_range())) - .filter_map(|stmt| match stmt { - ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(), - ast::Stmt::Item(_) => None, - ast::Stmt::LetStmt(stmt) => stmt.initializer(), + .flat_map(|stmt| match stmt { + ast::Stmt::ExprStmt(expr_stmt) => vec![expr_stmt.expr()], + ast::Stmt::Item(_) => vec![None], + ast::Stmt::LetStmt(stmt) => vec![ + stmt.initializer(), + stmt.let_else() + .and_then(|le| le.block_expr()) + .map(|be| ast::Expr::BlockExpr(be)), + ], }) + .filter_map(std::convert::identity) .for_each(|expr| preorder_expr(&expr, cb)); if let Some(expr) = parent .tail_expr() @@ -6233,4 +6245,39 @@ fn $0fun_name(a: i32, b: i32) { cov_mark::check!(extract_function_in_braces_is_not_applicable); check_assist_not_applicable(extract_function, r"fn foo(arr: &mut $0[$0i32]) {}"); } + + #[test] + fn no_parameter_for_variable_used_only_let_else() { + check_assist( + extract_function, + r#" +fn foo() -> u32 { + let x = 5; + + $0let Some(y) = Some(1) else { + return x * 2; + };$0 + + y +}"#, + r#" +fn foo() -> u32 { + let x = 5; + + let y = match fun_name(x) { + Ok(value) => value, + Err(value) => return value, + }; + + y +} + +fn $0fun_name(x: u32) -> Result<_, u32> { + let Some(y) = Some(1) else { + return Err(x * 2); + }; + Ok(y) +}"#, + ); + } }