about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-04-16 09:26:09 +0000
committerbors <bors@rust-lang.org>2022-04-16 09:26:09 +0000
commit40396b463e5096af10a7480ddf1c3ba299b58d5f (patch)
tree40ffd981d2fc40021b20717d3edb9a05d93042a5
parent66c232d03baadecf5318a77837f0f8b6166c0796 (diff)
parentc53412046f8af55ed462fd4c213d93ed192827b7 (diff)
downloadrust-40396b463e5096af10a7480ddf1c3ba299b58d5f.tar.gz
rust-40396b463e5096af10a7480ddf1c3ba299b58d5f.zip
Auto merge of #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 #11438 : completion detail shows `{unknown}` for return types in async functions.

#### API changes
Add `hir::Function::async_ret_type` method
-rw-r--r--crates/hir/src/lib.rs23
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs15
-rw-r--r--crates/ide_completion/src/render/function.rs5
-rw-r--r--crates/ide_completion/src/tests/expression.rs40
4 files changed, 77 insertions, 6 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 06056217fdb..5aa1ca7e0ba 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1358,12 +1358,29 @@ impl Function {
     /// Get this function's return type
     pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
         let resolver = self.id.resolver(db.upcast());
-        let ret_type = &db.function_data(self.id).ret_type;
-        let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
-        let ty = ctx.lower_ty(ret_type);
+        let substs = TyBuilder::placeholder_subst(db, self.id);
+        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
+        let ty = callable_sig.ret().clone();
         Type::new_with_resolver_inner(db, &resolver, ty)
     }
 
+    pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
+        if !self.is_async(db) {
+            return None;
+        }
+        let resolver = self.id.resolver(db.upcast());
+        let substs = TyBuilder::placeholder_subst(db, self.id);
+        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
+        let ret_ty = callable_sig.ret().clone();
+        for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
+            if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
+                return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
+            }
+        }
+        never!("Async fn ret_type should be impl Future");
+        None
+    }
+
     pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
         if !db.function_data(self.id).has_self_param() {
             return None;
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index b2cda87f93e..4df7c4177c8 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -692,7 +692,14 @@ impl FunctionBody {
                         (constness, expr.clone(), infer_expr_opt(expr))
                     },
                     ast::Fn(fn_) => {
-                        (fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(sema.to_def(&fn_)?.ret_type(sema.db)))
+                        let func = sema.to_def(&fn_)?;
+                        let mut ret_ty = func.ret_type(sema.db);
+                        if func.is_async(sema.db) {
+                            if let Some(async_ret) = func.async_ret_type(sema.db) {
+                                ret_ty = async_ret;
+                            }
+                        }
+                        (fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(ret_ty))
                     },
                     ast::Static(statik) => {
                         (true, statik.body(), Some(sema.to_def(&statik)?.ty(sema.db)))
@@ -4026,6 +4033,7 @@ fn $0fun_name(n: i32) -> i32 {
         check_assist(
             extract_function,
             r#"
+//- minicore: future
 fn main() {
     $0some_function().await;$0
 }
@@ -4055,6 +4063,7 @@ async fn some_function() {
         check_assist(
             extract_function,
             r#"
+//- minicore: future, result
 async fn foo() -> Result<(), ()> {
     $0async {}.await;
     Err(())?$0
@@ -4065,7 +4074,7 @@ async fn foo() -> Result<(), ()> {
     fun_name().await?
 }
 
-async fn $0fun_name() -> _ {
+async fn $0fun_name() -> Result<(), ()> {
     async {}.await;
     Err(())?
 }
@@ -4078,6 +4087,7 @@ async fn $0fun_name() -> _ {
         check_assist(
             extract_function,
             r#"
+//- minicore: future
 async fn foo() -> i32 {
     loop {
         let n = 1;$0
@@ -4119,6 +4129,7 @@ async fn $0fun_name() -> Result<i32, i32> {
         check_assist(
             extract_function,
             r#"
+//- minicore: future
 fn main() {
     $0function_call("a", some_function().await);$0
 }
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 38520e1832f..9e5f91db39c 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -228,7 +228,7 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
 }
 
 fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
-    let ret_ty = func.ret_type(db);
+    let mut ret_ty = func.ret_type(db);
     let mut detail = String::new();
 
     if func.is_const(db) {
@@ -236,6 +236,9 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
     }
     if func.is_async(db) {
         format_to!(detail, "async ");
+        if let Some(async_ret) = func.async_ret_type(db) {
+            ret_ty = async_ret;
+        }
     }
     if func.is_unsafe_to_call(db) {
         format_to!(detail, "unsafe ");
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index f1950235d46..77296d9099f 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -602,3 +602,43 @@ fn func() {
         "#]],
     );
 }
+
+#[test]
+fn detail_impl_trait_in_return_position() {
+    check_empty(
+        r"
+//- minicore: sized
+trait Trait<T> {}
+fn foo<U>() -> impl Trait<U> {}
+fn main() {
+    self::$0
+}
+",
+        expect![[r"
+            tt Trait
+            fn main() fn()
+            fn foo()  fn() -> impl Trait<U>
+        "]],
+    );
+}
+
+#[test]
+fn detail_async_fn() {
+    check_empty(
+        r#"
+//- minicore: future, sized
+trait Trait<T> {}
+async fn foo() -> u8 {}
+async fn bar<U>() -> impl Trait<U> {}
+fn main() {
+    self::$0
+}
+"#,
+        expect![[r"
+            tt Trait
+            fn main() fn()
+            fn bar()  async fn() -> impl Trait<U>
+            fn foo()  async fn() -> u8
+        "]],
+    );
+}