diff options
| author | bors <bors@rust-lang.org> | 2024-08-01 14:16:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-08-01 14:16:08 +0000 |
| commit | 61ebcf631b3c3267f6166fc97917da7c30d4d846 (patch) | |
| tree | 2f11a7718a53f2b9b6b6c9ed5ff17dac4a01effe | |
| parent | 9ec4844925a37aae5665491b43ca526d47501d48 (diff) | |
| parent | 44f5392f5a7f6ab4a6e8c42a436ef7cda54929d0 (diff) | |
| download | rust-61ebcf631b3c3267f6166fc97917da7c30d4d846.tar.gz rust-61ebcf631b3c3267f6166fc97917da7c30d4d846.zip | |
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`
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 4e52d28051b..6f5c68d4b5c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -2,8 +2,12 @@ use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ - ast::{self, BlockExpr, ExprStmt}, - AstNode, AstPtr, + ast::{ + self, + edit::{AstNodeEdit, IndentLevel}, + BlockExpr, Expr, ExprStmt, + }, + AstNode, AstPtr, TextSize, }; use text_edit::TextEdit; @@ -119,6 +123,38 @@ fn add_missing_ok_or_some( return None; } + if d.actual.is_unit() { + if let Expr::BlockExpr(block) = &expr { + if block.tail_expr().is_none() { + let mut builder = TextEdit::builder(); + let block_indent = block.indent_level(); + + if block.statements().count() == 0 { + // Empty block + let indent = block_indent + 1; + builder.insert( + block.syntax().text_range().start() + TextSize::from(1), + format!("\n{indent}{variant_name}(())\n{block_indent}"), + ); + } else { + let indent = IndentLevel::from(1); + builder.insert( + block.syntax().text_range().end() - TextSize::from(1), + format!("{indent}{variant_name}(())\n{block_indent}"), + ); + } + + let source_change = SourceChange::from_text_edit( + expr_ptr.file_id.original_file(ctx.sema.db), + builder.finish(), + ); + let name = format!("Insert {variant_name}(()) as the tail of this block"); + acc.push(fix("insert_wrapped_unit", &name, source_change, expr_range)); + } + return Some(()); + } + } + let mut builder = TextEdit::builder(); builder.insert(expr.syntax().text_range().start(), format!("{variant_name}(")); builder.insert(expr.syntax().text_range().end(), ")".to_owned()); @@ -534,6 +570,36 @@ fn div(x: i32, y: i32) -> MyResult<i32> { } #[test] + fn test_wrapped_unit_as_block_tail_expr() { + check_fix( + r#" +//- minicore: result +fn foo() -> Result<(), ()> { + foo(); +}$0 + "#, + r#" +fn foo() -> Result<(), ()> { + foo(); + Ok(()) +} + "#, + ); + + check_fix( + r#" +//- minicore: result +fn foo() -> Result<(), ()> {}$0 + "#, + r#" +fn foo() -> Result<(), ()> { + Ok(()) +} + "#, + ); + } + + #[test] fn test_in_const_and_static() { check_fix( r#" |
