mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 19:17:43 +00:00
Auto merge of #116084 - fmease:rustdoc-fix-x-crate-async-fn, r=GuillaumeGomez
rustdoc: correctly render the return type of cross-crate async fns Fixes #115760.
This commit is contained in:
commit
0288f2e195
@ -1108,10 +1108,7 @@ fn clean_function<'tcx>(
|
|||||||
clean_args_from_types_and_names(cx, sig.decl.inputs, names)
|
clean_args_from_types_and_names(cx, sig.decl.inputs, names)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
|
let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args);
|
||||||
if sig.header.is_async() {
|
|
||||||
decl.output = decl.sugared_async_return_type();
|
|
||||||
}
|
|
||||||
(generics, decl)
|
(generics, decl)
|
||||||
});
|
});
|
||||||
Box::new(Function { decl, generics })
|
Box::new(Function { decl, generics })
|
||||||
@ -1162,12 +1159,16 @@ fn clean_args_from_types_and_body_id<'tcx>(
|
|||||||
fn clean_fn_decl_with_args<'tcx>(
|
fn clean_fn_decl_with_args<'tcx>(
|
||||||
cx: &mut DocContext<'tcx>,
|
cx: &mut DocContext<'tcx>,
|
||||||
decl: &hir::FnDecl<'tcx>,
|
decl: &hir::FnDecl<'tcx>,
|
||||||
|
header: Option<&hir::FnHeader>,
|
||||||
args: Arguments,
|
args: Arguments,
|
||||||
) -> FnDecl {
|
) -> FnDecl {
|
||||||
let output = match decl.output {
|
let mut output = match decl.output {
|
||||||
hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
|
hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
|
||||||
hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()),
|
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 }
|
FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,7 +1181,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
|
|||||||
|
|
||||||
// We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
|
// We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
|
||||||
// but shouldn't change any code meaning.
|
// 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 {
|
FnDecl {
|
||||||
output,
|
output,
|
||||||
@ -2566,7 +2571,7 @@ fn clean_bare_fn_ty<'tcx>(
|
|||||||
.map(|x| clean_generic_param(cx, None, x))
|
.map(|x| clean_generic_param(cx, None, x))
|
||||||
.collect();
|
.collect();
|
||||||
let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names);
|
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)
|
(generic_params, decl)
|
||||||
});
|
});
|
||||||
BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
|
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
|
// NOTE: generics must be cleaned before args
|
||||||
let generics = clean_generics(generics, cx);
|
let generics = clean_generics(generics, cx);
|
||||||
let args = clean_args_from_types_and_names(cx, decl.inputs, names);
|
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)
|
(generics, decl)
|
||||||
});
|
});
|
||||||
ForeignFunctionItem(Box::new(Function { decl, generics }))
|
ForeignFunctionItem(Box::new(Function { decl, generics }))
|
||||||
|
@ -1384,28 +1384,6 @@ impl FnDecl {
|
|||||||
pub(crate) fn self_type(&self) -> Option<SelfTy> {
|
pub(crate) fn self_type(&self) -> Option<SelfTy> {
|
||||||
self.inputs.values.get(0).and_then(|v| v.to_self())
|
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)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
@ -1617,6 +1595,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.
|
/// Checks if this is a `T::Name` path for an associated type.
|
||||||
pub(crate) fn is_assoc_ty(&self) -> bool {
|
pub(crate) fn is_assoc_ty(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
19
tests/rustdoc/inline_cross/async-fn.rs
Normal file
19
tests/rustdoc/inline_cross/async-fn.rs
Normal file
@ -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;
|
18
tests/rustdoc/inline_cross/auxiliary/async-fn.rs
Normal file
18
tests/rustdoc/inline_cross/auxiliary/async-fn.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -33,9 +33,3 @@ pub struct Foo;
|
|||||||
impl Foo {
|
impl Foo {
|
||||||
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
|
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bar;
|
|
||||||
|
|
||||||
impl Bar {
|
|
||||||
pub async fn async_foo(&self) {}
|
|
||||||
}
|
|
||||||
|
@ -33,15 +33,7 @@ pub use impl_trait_aux::func4;
|
|||||||
// @!has - '//pre[@class="rust item-decl"]' 'where'
|
// @!has - '//pre[@class="rust item-decl"]' 'where'
|
||||||
pub use impl_trait_aux::func5;
|
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 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"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
|
||||||
// @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
|
// @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
|
||||||
pub use impl_trait_aux::Foo;
|
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;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user