Skip to content

Commit 40396b4

Browse files
committed
Auto merge of rust-lang#11991 - iDawer:completion_detail.impl_trait, r=iDawer
fix: completion detail shows `{unknown}` for async functions and for RPITs Fix: completion detail shows `{unknown}` for `impl Trait` in return position. Fix rust-lang#11438 : completion detail shows `{unknown}` for return types in async functions. #### API changes Add `hir::Function::async_ret_type` method
2 parents 66c232d + c534120 commit 40396b4

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed

crates/hir/src/lib.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,12 +1358,29 @@ impl Function {
13581358
/// Get this function's return type
13591359
pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
13601360
let resolver = self.id.resolver(db.upcast());
1361-
let ret_type = &db.function_data(self.id).ret_type;
1362-
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1363-
let ty = ctx.lower_ty(ret_type);
1361+
let substs = TyBuilder::placeholder_subst(db, self.id);
1362+
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1363+
let ty = callable_sig.ret().clone();
13641364
Type::new_with_resolver_inner(db, &resolver, ty)
13651365
}
13661366

1367+
pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
1368+
if !self.is_async(db) {
1369+
return None;
1370+
}
1371+
let resolver = self.id.resolver(db.upcast());
1372+
let substs = TyBuilder::placeholder_subst(db, self.id);
1373+
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1374+
let ret_ty = callable_sig.ret().clone();
1375+
for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
1376+
if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
1377+
return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
1378+
}
1379+
}
1380+
never!("Async fn ret_type should be impl Future");
1381+
None
1382+
}
1383+
13671384
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
13681385
if !db.function_data(self.id).has_self_param() {
13691386
return None;

crates/ide_assists/src/handlers/extract_function.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,14 @@ impl FunctionBody {
692692
(constness, expr.clone(), infer_expr_opt(expr))
693693
},
694694
ast::Fn(fn_) => {
695-
(fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(sema.to_def(&fn_)?.ret_type(sema.db)))
695+
let func = sema.to_def(&fn_)?;
696+
let mut ret_ty = func.ret_type(sema.db);
697+
if func.is_async(sema.db) {
698+
if let Some(async_ret) = func.async_ret_type(sema.db) {
699+
ret_ty = async_ret;
700+
}
701+
}
702+
(fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(ret_ty))
696703
},
697704
ast::Static(statik) => {
698705
(true, statik.body(), Some(sema.to_def(&statik)?.ty(sema.db)))
@@ -4026,6 +4033,7 @@ fn $0fun_name(n: i32) -> i32 {
40264033
check_assist(
40274034
extract_function,
40284035
r#"
4036+
//- minicore: future
40294037
fn main() {
40304038
$0some_function().await;$0
40314039
}
@@ -4055,6 +4063,7 @@ async fn some_function() {
40554063
check_assist(
40564064
extract_function,
40574065
r#"
4066+
//- minicore: future, result
40584067
async fn foo() -> Result<(), ()> {
40594068
$0async {}.await;
40604069
Err(())?$0
@@ -4065,7 +4074,7 @@ async fn foo() -> Result<(), ()> {
40654074
fun_name().await?
40664075
}
40674076
4068-
async fn $0fun_name() -> _ {
4077+
async fn $0fun_name() -> Result<(), ()> {
40694078
async {}.await;
40704079
Err(())?
40714080
}
@@ -4078,6 +4087,7 @@ async fn $0fun_name() -> _ {
40784087
check_assist(
40794088
extract_function,
40804089
r#"
4090+
//- minicore: future
40814091
async fn foo() -> i32 {
40824092
loop {
40834093
let n = 1;$0
@@ -4119,6 +4129,7 @@ async fn $0fun_name() -> Result<i32, i32> {
41194129
check_assist(
41204130
extract_function,
41214131
r#"
4132+
//- minicore: future
41224133
fn main() {
41234134
$0function_call("a", some_function().await);$0
41244135
}

crates/ide_completion/src/render/function.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,17 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
228228
}
229229

230230
fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
231-
let ret_ty = func.ret_type(db);
231+
let mut ret_ty = func.ret_type(db);
232232
let mut detail = String::new();
233233

234234
if func.is_const(db) {
235235
format_to!(detail, "const ");
236236
}
237237
if func.is_async(db) {
238238
format_to!(detail, "async ");
239+
if let Some(async_ret) = func.async_ret_type(db) {
240+
ret_ty = async_ret;
241+
}
239242
}
240243
if func.is_unsafe_to_call(db) {
241244
format_to!(detail, "unsafe ");

crates/ide_completion/src/tests/expression.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,3 +602,43 @@ fn func() {
602602
"#]],
603603
);
604604
}
605+
606+
#[test]
607+
fn detail_impl_trait_in_return_position() {
608+
check_empty(
609+
r"
610+
//- minicore: sized
611+
trait Trait<T> {}
612+
fn foo<U>() -> impl Trait<U> {}
613+
fn main() {
614+
self::$0
615+
}
616+
",
617+
expect![[r"
618+
tt Trait
619+
fn main() fn()
620+
fn foo() fn() -> impl Trait<U>
621+
"]],
622+
);
623+
}
624+
625+
#[test]
626+
fn detail_async_fn() {
627+
check_empty(
628+
r#"
629+
//- minicore: future, sized
630+
trait Trait<T> {}
631+
async fn foo() -> u8 {}
632+
async fn bar<U>() -> impl Trait<U> {}
633+
fn main() {
634+
self::$0
635+
}
636+
"#,
637+
expect![[r"
638+
tt Trait
639+
fn main() fn()
640+
fn bar() async fn() -> impl Trait<U>
641+
fn foo() async fn() -> u8
642+
"]],
643+
);
644+
}

0 commit comments

Comments
 (0)