Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22077 from Albab-Hasan/fix-22072-if-let-match-paren-panic
fix: avoid panic in replace_if_let_with_match on jump scrutinee
A4-Tacks 5 weeks ago
parent 8edb111 · parent 7f0acb3 · commit 251df51
-rw-r--r--crates/ide-assists/src/handlers/replace_if_let_with_match.rs36
1 files changed, 36 insertions, 0 deletions
diff --git a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index 20cd647e3b..0badad7d0c 100644
--- a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
@@ -132,6 +132,11 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
};
let arms = cond_bodies.into_iter().map(make_match_arm).chain([else_arm]);
let expr = scrutinee_to_be_expr.reset_indent();
+ let expr = if match_scrutinee_needs_paren(&expr) {
+ make.expr_paren(expr).into()
+ } else {
+ expr
+ };
let match_expr = make.expr_match(expr, make.match_arm_list(arms)).indent(indent);
match_expr.into()
};
@@ -419,6 +424,17 @@ fn let_and_guard(cond: &ast::Expr) -> (Option<ast::LetExpr>, Option<ast::Expr>)
}
}
+fn match_scrutinee_needs_paren(expr: &ast::Expr) -> bool {
+ let make = SyntaxFactory::without_mappings();
+ let fake_scrutinee = make.expr_unit();
+ let fake_match = make.expr_match(fake_scrutinee, make.match_arm_list(std::iter::empty()));
+ let Some(fake_expr) = fake_match.expr() else {
+ stdx::never!();
+ return false;
+ };
+ expr.needs_parens_in_place_of(fake_match.syntax(), fake_expr.syntax())
+}
+
fn and_bin_expr_left(expr: &ast::BinExpr) -> ast::BinExpr {
if expr.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And))
&& let Some(ast::Expr::BinExpr(left)) = expr.lhs()
@@ -448,6 +464,26 @@ fn main() {
}
#[test]
+ fn test_if_with_match_paren_jump_scrutinee() {
+ check_assist(
+ replace_if_let_with_match,
+ r#"
+fn f() {
+ if $0(return) {}
+}
+"#,
+ r#"
+fn f() {
+ match (return) {
+ true => {}
+ false => (),
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
fn test_if_with_match_no_else() {
check_assist(
replace_if_let_with_match,