about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-19 10:34:36 +0000
committerbors <bors@rust-lang.org>2022-05-19 10:34:36 +0000
commit4f7d1a9d699ce7d30946f4ae26622b95e2c75372 (patch)
tree5731c26a83724c64f706fa85fd72ed963c3c4e31
parentd5ab27a0bf46913484d830b8bbeeaafb01c941ed (diff)
parent018975b0418f5b5baa1a5403fce32a53d95e5068 (diff)
downloadrust-4f7d1a9d699ce7d30946f4ae26622b95e2c75372.tar.gz
rust-4f7d1a9d699ce7d30946f4ae26622b95e2c75372.zip
Auto merge of #12309 - Veykril:completion, r=Veykril
fix: Fix incorrect expected type in completions for trailing match arms

Fixes https://github.com/rust-lang/rust-analyzer/issues/12264
-rw-r--r--crates/ide-completion/src/context.rs44
1 files changed, 42 insertions, 2 deletions
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index fbf3278ad1f..e51ae0dc3b5 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -802,9 +802,19 @@ impl<'a> CompletionContext<'a> {
                             )
                         }
                     },
+                    // match foo { $0 }
+                    // match foo { ..., pat => $0 }
                     ast::MatchExpr(it) => {
-                        cov_mark::hit!(expected_type_match_arm_without_leading_char);
-                        let ty = it.expr().and_then(|e| self.sema.type_of_expr(&e)).map(TypeInfo::original);
+                        let ty = if self.previous_token_is(T![=>]) {
+                            // match foo { ..., pat => $0 }
+                            cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
+                            cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
+                            self.sema.type_of_expr(&it.into())
+                        } else {
+                            // match foo { $0 }
+                            cov_mark::hit!(expected_type_match_arm_without_leading_char);
+                            it.expr().and_then(|e| self.sema.type_of_expr(&e))
+                        }.map(TypeInfo::original);
                         (ty, None)
                     },
                     ast::IfExpr(it) => {
@@ -1590,6 +1600,36 @@ fn foo() {
     }
 
     #[test]
+    fn expected_type_match_arm_body_without_leading_char() {
+        cov_mark::check!(expected_type_match_arm_body_without_leading_char);
+        check_expected_type_and_name(
+            r#"
+struct Foo;
+enum E { X }
+fn foo() -> Foo {
+   match E::X { E::X => $0 }
+}
+"#,
+            expect![[r#"ty: Foo, name: ?"#]],
+        );
+    }
+
+    #[test]
+    fn expected_type_match_body_arm_with_leading_char() {
+        cov_mark::check!(expected_type_match_arm_body_with_leading_char);
+        check_expected_type_and_name(
+            r#"
+struct Foo;
+enum E { X }
+fn foo() -> Foo {
+   match E::X { E::X => c$0 }
+}
+"#,
+            expect![[r#"ty: Foo, name: ?"#]],
+        );
+    }
+
+    #[test]
     fn expected_type_if_let_without_leading_char() {
         cov_mark::check!(expected_type_if_let_without_leading_char);
         check_expected_type_and_name(