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>
This commit is contained in:
bors[bot] 2021-11-08 13:12:03 +00:00 committed by GitHub
commit c5c11b87cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 9 deletions

View File

@ -58,6 +58,7 @@ pub(crate) struct PathCompletionContext {
pub(super) struct PatternContext { pub(super) struct PatternContext {
pub(super) refutability: PatternRefutability, pub(super) refutability: PatternRefutability,
pub(super) is_param: Option<ParamKind>, pub(super) is_param: Option<ParamKind>,
pub(super) has_type_ascription: bool,
} }
#[derive(Debug)] #[derive(Debug)]
@ -597,7 +598,8 @@ impl<'a> CompletionContext<'a> {
.map(|c| (Some(c.return_type()), None)) .map(|c| (Some(c.return_type()), None))
.unwrap_or((None, None)) .unwrap_or((None, None))
}, },
ast::Stmt(_it) => (None, None), ast::ParamList(__) => (None, None),
ast::Stmt(__) => (None, None),
ast::Item(__) => (None, None), ast::Item(__) => (None, None),
_ => { _ => {
match node.parent() { match node.parent() {
@ -708,15 +710,15 @@ impl<'a> CompletionContext<'a> {
return None; return None;
} }
let mut is_param = None; let mut is_param = None;
let refutability = bind_pat let (refutability, has_type_ascription) = bind_pat
.syntax() .syntax()
.ancestors() .ancestors()
.skip_while(|it| ast::Pat::can_cast(it.kind())) .skip_while(|it| ast::Pat::can_cast(it.kind()))
.next() .next()
.map_or(PatternRefutability::Irrefutable, |node| { .map_or((PatternRefutability::Irrefutable, false), |node| {
match_ast! { let refutability = match_ast! {
match node { match node {
ast::LetStmt(__) => PatternRefutability::Irrefutable, ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
ast::Param(param) => { ast::Param(param) => {
let is_closure_param = param let is_closure_param = param
.syntax() .syntax()
@ -729,16 +731,17 @@ impl<'a> CompletionContext<'a> {
} else { } else {
ParamKind::Function ParamKind::Function
}); });
PatternRefutability::Irrefutable return (PatternRefutability::Irrefutable, param.ty().is_some())
}, },
ast::MatchArm(__) => PatternRefutability::Refutable, ast::MatchArm(__) => PatternRefutability::Refutable,
ast::Condition(__) => PatternRefutability::Refutable, ast::Condition(__) => PatternRefutability::Refutable,
ast::ForExpr(__) => PatternRefutability::Irrefutable, ast::ForExpr(__) => PatternRefutability::Irrefutable,
_ => PatternRefutability::Irrefutable, _ => PatternRefutability::Irrefutable,
} }
} };
(refutability, false)
}); });
Some(PatternContext { refutability, is_param }) Some(PatternContext { refutability, is_param, has_type_ascription })
} }
fn classify_name_ref( fn classify_name_ref(
@ -1172,4 +1175,23 @@ fn foo() {
expect![[r#"ty: Foo, name: ?"#]], 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: ?"#]],
);
}
} }

View File

@ -86,7 +86,11 @@ fn render_pat(
if matches!( if matches!(
ctx.completion.pattern_ctx, 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(':');
pat.push(' '); pat.push(' ');

View File

@ -163,6 +163,21 @@ fn foo(a$0) {
ma makro!() #[macro_export] macro_rules! makro 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] #[test]