about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs70
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#"