diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 77a94403abb9..6925816c719d 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -563,10 +563,10 @@ fn analyze<'db>( /// Calculate the expected type and name of the cursor position. fn expected_type_and_name<'db>( sema: &Semantics<'db, RootDatabase>, - token: &SyntaxToken, + self_token: &SyntaxToken, name_like: &ast::NameLike, ) -> (Option>, Option) { - let token = prev_special_biased_token_at_trivia(token.clone()); + let token = prev_special_biased_token_at_trivia(self_token.clone()); let mut node = match token.parent() { Some(it) => it, None => return (None, None), @@ -756,7 +756,15 @@ fn expected_type_and_name<'db>( .map(|c| (Some(c.return_type()), None)) .unwrap_or((None, None)) }, - ast::ParamList(_) => (None, None), + ast::ParamList(it) => { + let closure = it.syntax().parent().and_then(ast::ClosureExpr::cast); + let ty = closure + .filter(|_| it.syntax().text_range().end() <= self_token.text_range().start()) + .and_then(|it| sema.type_of_expr(&it.into())); + ty.and_then(|ty| ty.original.as_callable(sema.db)) + .map(|c| (Some(c.return_type()), None)) + .unwrap_or((None, None)) + }, ast::Stmt(_) => (None, None), ast::Item(_) => (None, None), _ => { @@ -1938,6 +1946,7 @@ fn prev_special_biased_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken { | T![|=] | T![&=] | T![^=] + | T![|] | T![return] | T![break] | T![continue] = prev.kind() diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index d9ec7915e3c7..5b0ce145c512 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -374,7 +374,6 @@ fn foo() -> u32 { #[test] fn expected_type_closure_param_return() { - // FIXME: make this work with `|| $0` check_expected_type_and_name( r#" //- minicore: fn @@ -382,6 +381,18 @@ fn foo() { bar(|| a$0); } +fn bar(f: impl FnOnce() -> u32) {} +"#, + expect![[r#"ty: u32, name: ?"#]], + ); + + check_expected_type_and_name( + r#" +//- minicore: fn +fn foo() { + bar(|| $0); +} + fn bar(f: impl FnOnce() -> u32) {} "#, expect![[r#"ty: u32, name: ?"#]],