From e0d857720598e15afab57316d4bb467a3086b20f Mon Sep 17 00:00:00 2001 From: Kao-Wei Yeh Date: Sun, 26 Apr 2026 22:00:38 +0800 Subject: [PATCH 1/3] TypeMismatch quick fix error when insert to_owned() to tail expr of block. --- .../src/handlers/type_mismatch.rs | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 250c692d16f8..2ae30b3099e6 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -327,8 +327,16 @@ fn str_ref_to_owned( let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?; let to_owned = ".to_owned()".to_owned(); - - let edit = TextEdit::insert(range.end(), to_owned); + let mut edit_expr = expr.clone(); + while let ast::Expr::BlockExpr(block) = edit_expr.clone() { + match block.tail_expr() { + Some(tail) => edit_expr = tail, + None => break, + } + } + let hir::FileRange { range: edit_range, .. } = + ctx.sema.original_range_opt(edit_expr.syntax())?; + let edit = TextEdit::insert(edit_range.end(), to_owned); let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit); acc.push(fix("str_ref_to_owned", "Add .to_owned() here", source_change, range)); @@ -342,6 +350,39 @@ mod tests { check_has_fix, check_no_fix, }; + #[test] + fn str_ref_to_owned_in_block() { + check_has_fix( + r#" +struct String; +fn main() { + if true { String } else { "" }$0; +} + "#, + r#" +struct String; +fn main() { + if true { String } else { "".to_owned() }; +} + "#, + ); + + check_has_fix( + r#" +struct String; +fn main() { + if true { String } else { { "" } }$0; +} + "#, + r#" +struct String; +fn main() { + if true { String } else { { "".to_owned() } }; +} + "#, + ); + } + #[test] fn missing_reference() { check_diagnostics( From a85999b4c8a058ba3b1373f2292420a4e0836424 Mon Sep 17 00:00:00 2001 From: Kao-Wei Yeh Date: Tue, 28 Apr 2026 00:59:57 +0800 Subject: [PATCH 2/3] Fix `add_reference` error when using on tail expr of block. --- .../src/handlers/type_mismatch.rs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 2ae30b3099e6..f8c8e2c82e87 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -327,16 +327,8 @@ fn str_ref_to_owned( let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?; let to_owned = ".to_owned()".to_owned(); - let mut edit_expr = expr.clone(); - while let ast::Expr::BlockExpr(block) = edit_expr.clone() { - match block.tail_expr() { - Some(tail) => edit_expr = tail, - None => break, - } - } - let hir::FileRange { range: edit_range, .. } = - ctx.sema.original_range_opt(edit_expr.syntax())?; - let edit = TextEdit::insert(edit_range.end(), to_owned); + + let edit = TextEdit::insert(range.end(), to_owned); let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit); acc.push(fix("str_ref_to_owned", "Add .to_owned() here", source_change, range)); @@ -351,33 +343,38 @@ mod tests { }; #[test] - fn str_ref_to_owned_in_block() { - check_has_fix( + fn add_reference_when_tail_expr_of_block() { + check_fix( r#" -struct String; fn main() { - if true { String } else { "" }$0; + let a = 0; + let b = 1; + if false { &a } else { b$0 }; } "#, r#" -struct String; fn main() { - if true { String } else { "".to_owned() }; + let a = 0; + let b = 1; + if false { &a } else { &b }; } "#, ); + } + #[test] + fn str_ref_to_owned_when_tail_expr_of_block() { check_has_fix( r#" struct String; fn main() { - if true { String } else { { "" } }$0; + if true { String } else { ""$0 }; } "#, r#" struct String; fn main() { - if true { String } else { { "".to_owned() } }; + if true { String } else { "".to_owned() }; } "#, ); From 4c20a4d196a8549e37808e8034eb21df72c2cc2d Mon Sep 17 00:00:00 2001 From: Kao-Wei Yeh Date: Sun, 3 May 2026 19:38:38 +0800 Subject: [PATCH 3/3] Move `type_mismatch` logic to `ide-diagnostics` --- crates/ide-diagnostics/src/handlers/type_mismatch.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index f8c8e2c82e87..627171bdcb2a 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -68,7 +68,16 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::TypeMismatch<'_>) -> Option< let mut fixes = Vec::new(); if let Some(expr_ptr) = d.expr_or_pat.value.cast::() { - let expr_ptr = &InFile { file_id: d.expr_or_pat.file_id, value: expr_ptr }; + let file_id = d.expr_or_pat.file_id; + let root = ctx.sema.db.parse_or_expand(file_id); + let mut expr = expr_ptr.to_node(&root); + while let ast::Expr::BlockExpr(block) = expr.clone() { + match block.tail_expr() { + Some(tail) => expr = tail, + None => break, + } + } + let expr_ptr = &InFile { file_id, value: AstPtr::new(&expr) }; add_reference(ctx, d, expr_ptr, &mut fixes); add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); remove_unnecessary_wrapper(ctx, d, expr_ptr, &mut fixes);