about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-29 17:39:15 +0000
committerGitHub <noreply@github.com>2021-05-29 17:39:15 +0000
commitf6da603c7fe56c19a275dc7bab1f30fe1ad39707 (patch)
tree222351c552f11aed7e8f18a5447fc9c15afa42e0
parent0438e2ceaa89959fe3a1b21e5311a17b08b6fc6d (diff)
parent54d60fdee9a49e2081837cc6445c61dec0b303af (diff)
downloadrust-f6da603c7fe56c19a275dc7bab1f30fe1ad39707.tar.gz
rust-f6da603c7fe56c19a275dc7bab1f30fe1ad39707.zip
Merge #9050
9050: hir_ty: use async ret type for inference inside async bodies r=flodiebold a=cynecx

Fixes #9004.

Co-authored-by: cynecx <me@cynecx.net>
-rw-r--r--crates/hir_def/src/data.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs1
-rw-r--r--crates/hir_def/src/item_tree/lower.rs8
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs1
-rw-r--r--crates/hir_ty/src/infer.rs8
-rw-r--r--crates/hir_ty/src/tests/traits.rs49
6 files changed, 65 insertions, 4 deletions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index a04f73352bc..d2bb381be02 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -22,6 +22,7 @@ pub struct FunctionData {
     pub name: Name,
     pub params: Vec<Interned<TypeRef>>,
     pub ret_type: Interned<TypeRef>,
+    pub async_ret_type: Option<Interned<TypeRef>>,
     pub attrs: Attrs,
     pub visibility: RawVisibility,
     pub abi: Option<Interned<str>>,
@@ -63,6 +64,7 @@ impl FunctionData {
                 })
                 .collect(),
             ret_type: func.ret_type.clone(),
+            async_ret_type: func.async_ret_type.clone(),
             attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
             visibility: item_tree[func.visibility].clone(),
             abi: func.abi.clone(),
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index c4d20c416b4..227337a8df1 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -580,6 +580,7 @@ pub struct Function {
     pub abi: Option<Interned<str>>,
     pub params: IdRange<Param>,
     pub ret_type: Interned<TypeRef>,
+    pub async_ret_type: Option<Interned<TypeRef>>,
     pub ast_id: FileAstId<ast::Fn>,
     pub(crate) flags: FnFlags,
 }
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index b83adec46af..6208facd54e 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -356,12 +356,13 @@ impl<'a> Ctx<'a> {
             _ => TypeRef::unit(),
         };
 
-        let ret_type = if func.async_token().is_some() {
+        let (ret_type, async_ret_type) = if func.async_token().is_some() {
+            let async_ret_type = ret_type.clone();
             let future_impl = desugar_future_path(ret_type);
             let ty_bound = Interned::new(TypeBound::Path(future_impl));
-            TypeRef::ImplTrait(vec![ty_bound])
+            (TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
         } else {
-            ret_type
+            (ret_type, None)
         };
 
         let abi = func.abi().map(lower_abi);
@@ -395,6 +396,7 @@ impl<'a> Ctx<'a> {
             abi,
             params,
             ret_type: Interned::new(ret_type),
+            async_ret_type: async_ret_type.map(Interned::new),
             ast_id,
             flags,
         };
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index d1ee697cb5d..cc9944a22f8 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -235,6 +235,7 @@ impl<'a> Printer<'a> {
                     abi,
                     params,
                     ret_type,
+                    async_ret_type: _,
                     ast_id: _,
                     flags,
                 } = &self.tree[it];
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 8cefd80f3ab..7a4268819b4 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -558,7 +558,13 @@ impl<'a> InferenceContext<'a> {
 
             self.infer_pat(*pat, &ty, BindingMode::default());
         }
-        let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT
+        let error_ty = &TypeRef::Error;
+        let return_ty = if data.is_async() {
+            data.async_ret_type.as_deref().unwrap_or(error_ty)
+        } else {
+            &*data.ret_type
+        };
+        let return_ty = self.make_ty_with_mode(return_ty, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT
         self.return_ty = return_ty;
     }
 
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 6ad96bfe383..7c0ff2170fe 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3660,3 +3660,52 @@ impl foo::Foo for u32 {
         "#]],
     );
 }
+
+#[test]
+fn infer_async_ret_type() {
+    check_types(
+        r#"
+//- /main.rs crate:main deps:core
+
+enum Result<T, E> {
+    Ok(T),
+    Err(E),
+}
+
+use Result::*;
+
+
+struct Fooey;
+
+impl Fooey {
+    fn collect<B: Convert>(self) -> B {
+        B::new()
+    }
+}
+
+trait Convert {
+    fn new() -> Self;
+}
+impl Convert for u32 {
+    fn new() -> Self {
+        0
+    }
+}
+
+async fn get_accounts() -> Result<u32, ()> {
+    let ret = Fooey.collect();
+    //                      ^ u32
+    Ok(ret)
+}
+
+//- /core.rs crate:core
+#[prelude_import] use future::*;
+mod future {
+    #[lang = "future_trait"]
+    trait Future {
+        type Output;
+    }
+}
+"#,
+    );
+}