about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-11-08 13:12:03 +0000
committerGitHub <noreply@github.com>2021-11-08 13:12:03 +0000
commitc5c11b87cc28a2bc63d6125f67732c3adfa09917 (patch)
tree31758b7e7b046b2e7c1b1585e67677574dcde78d
parent2c0f433fd2e838ae181f87019b6f1fefe33c6f54 (diff)
parentf7e8136923170bde35540207bdb5b9075204c854 (diff)
downloadrust-c5c11b87cc28a2bc63d6125f67732c3adfa09917.tar.gz
rust-c5c11b87cc28a2bc63d6125f67732c3adfa09917.zip
Merge #10720
10720: fix: Don't ascribe types in pattern completion for param patterns twice r=Veykril a=Veykril

Fixes #10323
bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/ide_completion/src/context.rs38
-rw-r--r--crates/ide_completion/src/render/pattern.rs6
-rw-r--r--crates/ide_completion/src/tests/pattern.rs15
3 files changed, 50 insertions, 9 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 0cb484d5075..ac01968126d 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -58,6 +58,7 @@ pub(crate) struct PathCompletionContext {
 pub(super) struct PatternContext {
     pub(super) refutability: PatternRefutability,
     pub(super) is_param: Option<ParamKind>,
+    pub(super) has_type_ascription: bool,
 }
 
 #[derive(Debug)]
@@ -597,7 +598,8 @@ impl<'a> CompletionContext<'a> {
                             .map(|c| (Some(c.return_type()), None))
                             .unwrap_or((None, None))
                     },
-                    ast::Stmt(_it) => (None, None),
+                    ast::ParamList(__) => (None, None),
+                    ast::Stmt(__) => (None, None),
                     ast::Item(__) => (None, None),
                     _ => {
                         match node.parent() {
@@ -708,15 +710,15 @@ impl<'a> CompletionContext<'a> {
             return None;
         }
         let mut is_param = None;
-        let refutability = bind_pat
+        let (refutability, has_type_ascription) = bind_pat
             .syntax()
             .ancestors()
             .skip_while(|it| ast::Pat::can_cast(it.kind()))
             .next()
-            .map_or(PatternRefutability::Irrefutable, |node| {
-                match_ast! {
+            .map_or((PatternRefutability::Irrefutable, false), |node| {
+                let refutability = match_ast! {
                     match node {
-                        ast::LetStmt(__) => PatternRefutability::Irrefutable,
+                        ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
                         ast::Param(param) => {
                             let is_closure_param = param
                                 .syntax()
@@ -729,16 +731,17 @@ impl<'a> CompletionContext<'a> {
                             } else {
                                 ParamKind::Function
                             });
-                            PatternRefutability::Irrefutable
+                            return (PatternRefutability::Irrefutable, param.ty().is_some())
                         },
                         ast::MatchArm(__) => PatternRefutability::Refutable,
                         ast::Condition(__) => PatternRefutability::Refutable,
                         ast::ForExpr(__) => PatternRefutability::Irrefutable,
                         _ => PatternRefutability::Irrefutable,
                     }
-                }
+                };
+                (refutability, false)
             });
-        Some(PatternContext { refutability, is_param })
+        Some(PatternContext { refutability, is_param, has_type_ascription })
     }
 
     fn classify_name_ref(
@@ -1172,4 +1175,23 @@ fn foo() {
             expect![[r#"ty: Foo, name: ?"#]],
         );
     }
+
+    #[test]
+    fn expected_type_param_pat() {
+        check_expected_type_and_name(
+            r#"
+struct Foo { field: u32 }
+fn foo(a$0: Foo) {}
+"#,
+            expect![[r#"ty: Foo, name: ?"#]],
+        );
+        check_expected_type_and_name(
+            r#"
+struct Foo { field: u32 }
+fn foo($0: Foo) {}
+"#,
+            // FIXME make this work, currently fails due to pattern recovery eating the `:`
+            expect![[r#"ty: ?, name: ?"#]],
+        );
+    }
 }
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index e553ec8f860..888a5b4b0a7 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -86,7 +86,11 @@ fn render_pat(
 
     if matches!(
         ctx.completion.pattern_ctx,
-        Some(PatternContext { is_param: Some(ParamKind::Function), .. })
+        Some(PatternContext {
+            is_param: Some(ParamKind::Function),
+            has_type_ascription: false,
+            ..
+        })
     ) {
         pat.push(':');
         pat.push(' ');
diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs
index 3e10575b19e..6dd1b669988 100644
--- a/crates/ide_completion/src/tests/pattern.rs
+++ b/crates/ide_completion/src/tests/pattern.rs
@@ -163,6 +163,21 @@ fn foo(a$0) {
             ma makro!(…) #[macro_export] macro_rules! makro
         "##]],
     );
+    check(
+        r#"
+fn foo(a$0: Tuple) {
+}
+"#,
+        expect![[r##"
+            kw mut
+            bn Record    Record { field$1 }$0
+            st Record
+            bn Tuple     Tuple($1)$0
+            st Tuple
+            st Unit
+            ma makro!(…) #[macro_export] macro_rules! makro
+        "##]],
+    );
 }
 
 #[test]