Skip to content

Commit f149dc5

Browse files
committed
Auto merge of #17763 - ShoyuVanilla:wrap-unit, r=Veykril
fix: Insert a tail `Ok(())` for expr block instead of wrapping with `Ok` Fixes #17728 When type mismatch is `Result<(), E>, ()` or `Option<()>, ()` and target expr is a block expression, it is more reasonable to insert a wrapped unit - `Ok(())` or `Some(())` - as the tail expression of that block than wrapping the entire block with `Ok` or `Some`
2 parents 6c9ae75 + 3121a91 commit f149dc5

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

crates/ide-diagnostics/src/handlers/type_mismatch.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ use either::Either;
22
use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type};
33
use ide_db::{famous_defs::FamousDefs, source_change::SourceChange};
44
use syntax::{
5-
ast::{self, BlockExpr, ExprStmt},
6-
AstNode, AstPtr,
5+
ast::{
6+
self,
7+
edit::{AstNodeEdit, IndentLevel},
8+
BlockExpr, Expr, ExprStmt,
9+
},
10+
AstNode, AstPtr, TextSize,
711
};
812
use text_edit::TextEdit;
913

@@ -119,6 +123,38 @@ fn add_missing_ok_or_some(
119123
return None;
120124
}
121125

126+
if d.actual.is_unit() {
127+
if let Expr::BlockExpr(block) = &expr {
128+
if block.tail_expr().is_none() {
129+
let mut builder = TextEdit::builder();
130+
let block_indent = block.indent_level();
131+
132+
if block.statements().count() == 0 {
133+
// Empty block
134+
let indent = block_indent + 1;
135+
builder.insert(
136+
block.syntax().text_range().start() + TextSize::from(1),
137+
format!("\n{indent}{variant_name}(())\n{block_indent}"),
138+
);
139+
} else {
140+
let indent = IndentLevel::from(1);
141+
builder.insert(
142+
block.syntax().text_range().end() - TextSize::from(1),
143+
format!("{indent}{variant_name}(())\n{block_indent}"),
144+
);
145+
}
146+
147+
let source_change = SourceChange::from_text_edit(
148+
expr_ptr.file_id.original_file(ctx.sema.db),
149+
builder.finish(),
150+
);
151+
let name = format!("Insert {variant_name}(()) as the tail of this block");
152+
acc.push(fix("insert_wrapped_unit", &name, source_change, expr_range));
153+
}
154+
return Some(());
155+
}
156+
}
157+
122158
let mut builder = TextEdit::builder();
123159
builder.insert(expr.syntax().text_range().start(), format!("{variant_name}("));
124160
builder.insert(expr.syntax().text_range().end(), ")".to_owned());
@@ -533,6 +569,36 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
533569
);
534570
}
535571

572+
#[test]
573+
fn test_wrapped_unit_as_block_tail_expr() {
574+
check_fix(
575+
r#"
576+
//- minicore: result
577+
fn foo() -> Result<(), ()> {
578+
foo();
579+
}$0
580+
"#,
581+
r#"
582+
fn foo() -> Result<(), ()> {
583+
foo();
584+
Ok(())
585+
}
586+
"#,
587+
);
588+
589+
check_fix(
590+
r#"
591+
//- minicore: result
592+
fn foo() -> Result<(), ()> {}$0
593+
"#,
594+
r#"
595+
fn foo() -> Result<(), ()> {
596+
Ok(())
597+
}
598+
"#,
599+
);
600+
}
601+
536602
#[test]
537603
fn test_in_const_and_static() {
538604
check_fix(

0 commit comments

Comments
 (0)