Skip to content

Commit 0288f2e

Browse files
committed
Auto merge of rust-lang#116084 - fmease:rustdoc-fix-x-crate-async-fn, r=GuillaumeGomez
rustdoc: correctly render the return type of cross-crate async fns Fixes rust-lang#115760.
2 parents 6f13ea0 + 025a2cd commit 0288f2e

File tree

6 files changed

+72
-44
lines changed

6 files changed

+72
-44
lines changed

src/librustdoc/clean/mod.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1108,10 +1108,7 @@ fn clean_function<'tcx>(
11081108
clean_args_from_types_and_names(cx, sig.decl.inputs, names)
11091109
}
11101110
};
1111-
let mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
1112-
if sig.header.is_async() {
1113-
decl.output = decl.sugared_async_return_type();
1114-
}
1111+
let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args);
11151112
(generics, decl)
11161113
});
11171114
Box::new(Function { decl, generics })
@@ -1162,12 +1159,16 @@ fn clean_args_from_types_and_body_id<'tcx>(
11621159
fn clean_fn_decl_with_args<'tcx>(
11631160
cx: &mut DocContext<'tcx>,
11641161
decl: &hir::FnDecl<'tcx>,
1162+
header: Option<&hir::FnHeader>,
11651163
args: Arguments,
11661164
) -> FnDecl {
1167-
let output = match decl.output {
1165+
let mut output = match decl.output {
11681166
hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
11691167
hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()),
11701168
};
1169+
if let Some(header) = header && header.is_async() {
1170+
output = output.sugared_async_return_type();
1171+
}
11711172
FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
11721173
}
11731174

@@ -1180,7 +1181,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
11801181

11811182
// We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
11821183
// but shouldn't change any code meaning.
1183-
let output = clean_middle_ty(sig.output(), cx, None, None);
1184+
let mut output = clean_middle_ty(sig.output(), cx, None, None);
1185+
1186+
if let Some(did) = did && cx.tcx.asyncness(did).is_async() {
1187+
output = output.sugared_async_return_type();
1188+
}
11841189

11851190
FnDecl {
11861191
output,
@@ -2566,7 +2571,7 @@ fn clean_bare_fn_ty<'tcx>(
25662571
.map(|x| clean_generic_param(cx, None, x))
25672572
.collect();
25682573
let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names);
2569-
let decl = clean_fn_decl_with_args(cx, bare_fn.decl, args);
2574+
let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args);
25702575
(generic_params, decl)
25712576
});
25722577
BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
@@ -3077,7 +3082,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
30773082
// NOTE: generics must be cleaned before args
30783083
let generics = clean_generics(generics, cx);
30793084
let args = clean_args_from_types_and_names(cx, decl.inputs, names);
3080-
let decl = clean_fn_decl_with_args(cx, decl, args);
3085+
let decl = clean_fn_decl_with_args(cx, decl, None, args);
30813086
(generics, decl)
30823087
});
30833088
ForeignFunctionItem(Box::new(Function { decl, generics }))

src/librustdoc/clean/types.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -1384,28 +1384,6 @@ impl FnDecl {
13841384
pub(crate) fn self_type(&self) -> Option<SelfTy> {
13851385
self.inputs.values.get(0).and_then(|v| v.to_self())
13861386
}
1387-
1388-
/// Returns the sugared return type for an async function.
1389-
///
1390-
/// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1391-
/// will return `i32`.
1392-
///
1393-
/// # Panics
1394-
///
1395-
/// This function will panic if the return type does not match the expected sugaring for async
1396-
/// functions.
1397-
pub(crate) fn sugared_async_return_type(&self) -> Type {
1398-
if let Type::ImplTrait(v) = &self.output &&
1399-
let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
1400-
{
1401-
let bindings = trait_.bindings().unwrap();
1402-
let ret_ty = bindings[0].term();
1403-
let ty = ret_ty.ty().expect("Unexpected constant return term");
1404-
ty.clone()
1405-
} else {
1406-
panic!("unexpected desugaring of async function")
1407-
}
1408-
}
14091387
}
14101388

14111389
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1617,6 +1595,28 @@ impl Type {
16171595
}
16181596
}
16191597

1598+
/// Returns the sugared return type for an async function.
1599+
///
1600+
/// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1601+
/// will return `i32`.
1602+
///
1603+
/// # Panics
1604+
///
1605+
/// This function will panic if the return type does not match the expected sugaring for async
1606+
/// functions.
1607+
pub(crate) fn sugared_async_return_type(&self) -> Type {
1608+
if let Type::ImplTrait(v) = self &&
1609+
let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
1610+
{
1611+
let bindings = trait_.bindings().unwrap();
1612+
let ret_ty = bindings[0].term();
1613+
let ty = ret_ty.ty().expect("unexpected constant in async fn return term");
1614+
ty.clone()
1615+
} else {
1616+
panic!("unexpected async fn return type")
1617+
}
1618+
}
1619+
16201620
/// Checks if this is a `T::Name` path for an associated type.
16211621
pub(crate) fn is_assoc_ty(&self) -> bool {
16221622
match self {
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Regression test for issue #115760.
2+
// Check that we render the correct return type of free and
3+
// associated async functions reexported from external crates.
4+
5+
// aux-crate:async_fn=async-fn.rs
6+
// edition: 2021
7+
#![crate_name = "user"]
8+
9+
// @has user/fn.load.html
10+
// @has - '//pre[@class="rust item-decl"]' "pub async fn load() -> i32"
11+
pub use async_fn::load;
12+
13+
// @has user/trait.Load.html
14+
// @has - '//*[@id="tymethod.run"]' 'async fn run(&self) -> i32'
15+
pub use async_fn::Load;
16+
17+
// @has user/struct.Loader.html
18+
// @has - '//*[@id="method.run"]' 'async fn run(&self) -> i32'
19+
pub use async_fn::Loader;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(async_fn_in_trait)]
2+
// edition: 2021
3+
4+
pub async fn load() -> i32 {
5+
0
6+
}
7+
8+
pub trait Load {
9+
async fn run(&self) -> i32;
10+
}
11+
12+
pub struct Loader;
13+
14+
impl Load for Loader {
15+
async fn run(&self) -> i32 {
16+
1
17+
}
18+
}

tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs

-6
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,3 @@ pub struct Foo;
3333
impl Foo {
3434
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
3535
}
36-
37-
pub struct Bar;
38-
39-
impl Bar {
40-
pub async fn async_foo(&self) {}
41-
}

tests/rustdoc/inline_cross/impl_trait.rs

-8
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,7 @@ pub use impl_trait_aux::func4;
3333
// @!has - '//pre[@class="rust item-decl"]' 'where'
3434
pub use impl_trait_aux::func5;
3535

36-
// @has impl_trait/fn.async_fn.html
37-
// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
38-
pub use impl_trait_aux::async_fn;
39-
4036
// @has impl_trait/struct.Foo.html
4137
// @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
4238
// @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
4339
pub use impl_trait_aux::Foo;
44-
45-
// @has impl_trait/struct.Bar.html
46-
// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo("
47-
pub use impl_trait_aux::Bar;

0 commit comments

Comments
 (0)