about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2023-09-23 03:25:52 +0200
committerLeón Orell Valerian Liehr <me@fmease.dev>2023-09-25 15:57:04 +0200
commit025a2cda0ec511b6bc66f02dcddc408bf386e7ec (patch)
treedca59eec8719d8adb91df85fe225a78902a1beb7
parente4a361a48a59ead52b302aaa2e1d9d345264935a (diff)
downloadrust-025a2cda0ec511b6bc66f02dcddc408bf386e7ec.tar.gz
rust-025a2cda0ec511b6bc66f02dcddc408bf386e7ec.zip
rustdoc: correctly render ret ty of cross-crate async fns
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/types.rs44
-rw-r--r--tests/rustdoc/inline_cross/async-fn.rs19
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/async-fn.rs18
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs6
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs8
6 files changed, 72 insertions, 44 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 190b1b038b6..4b53f7a6b7c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1107,10 +1107,7 @@ fn clean_function<'tcx>(
                 clean_args_from_types_and_names(cx, sig.decl.inputs, names)
             }
         };
-        let mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
-        if sig.header.is_async() {
-            decl.output = decl.sugared_async_return_type();
-        }
+        let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args);
         (generics, decl)
     });
     Box::new(Function { decl, generics })
@@ -1161,12 +1158,16 @@ fn clean_args_from_types_and_body_id<'tcx>(
 fn clean_fn_decl_with_args<'tcx>(
     cx: &mut DocContext<'tcx>,
     decl: &hir::FnDecl<'tcx>,
+    header: Option<&hir::FnHeader>,
     args: Arguments,
 ) -> FnDecl {
-    let output = match decl.output {
+    let mut output = match decl.output {
         hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
         hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()),
     };
+    if let Some(header) = header && header.is_async() {
+        output = output.sugared_async_return_type();
+    }
     FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
 }
 
@@ -1179,7 +1180,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = clean_middle_ty(sig.output(), cx, None, None);
+    let mut output = clean_middle_ty(sig.output(), cx, None, None);
+
+    if let Some(did) = did && cx.tcx.asyncness(did).is_async() {
+        output = output.sugared_async_return_type();
+    }
 
     FnDecl {
         output,
@@ -2566,7 +2571,7 @@ fn clean_bare_fn_ty<'tcx>(
             .map(|x| clean_generic_param(cx, None, x))
             .collect();
         let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names);
-        let decl = clean_fn_decl_with_args(cx, bare_fn.decl, args);
+        let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args);
         (generic_params, decl)
     });
     BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
@@ -3077,7 +3082,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
                     // NOTE: generics must be cleaned before args
                     let generics = clean_generics(generics, cx);
                     let args = clean_args_from_types_and_names(cx, decl.inputs, names);
-                    let decl = clean_fn_decl_with_args(cx, decl, args);
+                    let decl = clean_fn_decl_with_args(cx, decl, None, args);
                     (generics, decl)
                 });
                 ForeignFunctionItem(Box::new(Function { decl, generics }))
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ef7794cc41e..d422a0b9a7f 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1380,28 +1380,6 @@ impl FnDecl {
     pub(crate) fn self_type(&self) -> Option<SelfTy> {
         self.inputs.values.get(0).and_then(|v| v.to_self())
     }
-
-    /// Returns the sugared return type for an async function.
-    ///
-    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
-    /// will return `i32`.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the return type does not match the expected sugaring for async
-    /// functions.
-    pub(crate) fn sugared_async_return_type(&self) -> Type {
-        if let Type::ImplTrait(v) = &self.output &&
-            let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
-        {
-            let bindings = trait_.bindings().unwrap();
-            let ret_ty = bindings[0].term();
-            let ty = ret_ty.ty().expect("Unexpected constant return term");
-            ty.clone()
-        } else {
-            panic!("unexpected desugaring of async function")
-        }
-    }
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1613,6 +1591,28 @@ impl Type {
         }
     }
 
+    /// Returns the sugared return type for an async function.
+    ///
+    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
+    /// will return `i32`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the return type does not match the expected sugaring for async
+    /// functions.
+    pub(crate) fn sugared_async_return_type(&self) -> Type {
+        if let Type::ImplTrait(v) = self &&
+            let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
+        {
+            let bindings = trait_.bindings().unwrap();
+            let ret_ty = bindings[0].term();
+            let ty = ret_ty.ty().expect("unexpected constant in async fn return term");
+            ty.clone()
+        } else {
+            panic!("unexpected async fn return type")
+        }
+    }
+
     /// Checks if this is a `T::Name` path for an associated type.
     pub(crate) fn is_assoc_ty(&self) -> bool {
         match self {
diff --git a/tests/rustdoc/inline_cross/async-fn.rs b/tests/rustdoc/inline_cross/async-fn.rs
new file mode 100644
index 00000000000..95e175aabd0
--- /dev/null
+++ b/tests/rustdoc/inline_cross/async-fn.rs
@@ -0,0 +1,19 @@
+// Regression test for issue #115760.
+// Check that we render the correct return type of free and
+// associated async functions reexported from external crates.
+
+// aux-crate:async_fn=async-fn.rs
+// edition: 2021
+#![crate_name = "user"]
+
+// @has user/fn.load.html
+// @has - '//pre[@class="rust item-decl"]' "pub async fn load() -> i32"
+pub use async_fn::load;
+
+// @has user/trait.Load.html
+// @has - '//*[@id="tymethod.run"]' 'async fn run(&self) -> i32'
+pub use async_fn::Load;
+
+// @has user/struct.Loader.html
+// @has - '//*[@id="method.run"]' 'async fn run(&self) -> i32'
+pub use async_fn::Loader;
diff --git a/tests/rustdoc/inline_cross/auxiliary/async-fn.rs b/tests/rustdoc/inline_cross/auxiliary/async-fn.rs
new file mode 100644
index 00000000000..767564ed145
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/async-fn.rs
@@ -0,0 +1,18 @@
+#![feature(async_fn_in_trait)]
+// edition: 2021
+
+pub async fn load() -> i32 {
+    0
+}
+
+pub trait Load {
+    async fn run(&self) -> i32;
+}
+
+pub struct Loader;
+
+impl Load for Loader {
+    async fn run(&self) -> i32 {
+        1
+    }
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
index 19433c9682b..42cfc3dc319 100644
--- a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
@@ -33,9 +33,3 @@ pub struct Foo;
 impl Foo {
     pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
 }
-
-pub struct Bar;
-
-impl Bar {
-    pub async fn async_foo(&self) {}
-}
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index b6a1552bc00..5c802c51486 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -33,15 +33,7 @@ pub use impl_trait_aux::func4;
 // @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func5;
 
-// @has impl_trait/fn.async_fn.html
-// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
-pub use impl_trait_aux::async_fn;
-
 // @has impl_trait/struct.Foo.html
 // @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
 // @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
 pub use impl_trait_aux::Foo;
-
-// @has impl_trait/struct.Bar.html
-// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo("
-pub use impl_trait_aux::Bar;