1
Fork 0

Properly render asyncness for traits without default body

This commit is contained in:
Michael Goulet 2022-11-02 17:33:25 +00:00
parent c0a7612728
commit 59be515128
4 changed files with 35 additions and 18 deletions

View file

@ -413,7 +413,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
/// Check if a function is async. /// Check if a function is async.
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
let node = tcx.hir().get_by_def_id(def_id.expect_local()); let node = tcx.hir().get_by_def_id(def_id.expect_local());
if let Some(fn_kind) = node.fn_kind() { fn_kind.asyncness() } else { hir::IsAsync::NotAsync } node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
} }
/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead. /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.

View file

@ -880,7 +880,7 @@ fn clean_fn_or_proc_macro<'tcx>(
ProcMacroItem(ProcMacro { kind, helpers }) ProcMacroItem(ProcMacro { kind, helpers })
} }
None => { None => {
let mut func = clean_function(cx, sig, generics, body_id); let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
clean_fn_decl_legacy_const_generics(&mut func, attrs); clean_fn_decl_legacy_const_generics(&mut func, attrs);
FunctionItem(func) FunctionItem(func)
} }
@ -917,16 +917,28 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attrib
} }
} }
enum FunctionArgs<'tcx> {
Body(hir::BodyId),
Names(&'tcx [Ident]),
}
fn clean_function<'tcx>( fn clean_function<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
sig: &hir::FnSig<'tcx>, sig: &hir::FnSig<'tcx>,
generics: &hir::Generics<'tcx>, generics: &hir::Generics<'tcx>,
body_id: hir::BodyId, args: FunctionArgs<'tcx>,
) -> Box<Function> { ) -> Box<Function> {
let (generics, decl) = enter_impl_trait(cx, |cx| { let (generics, decl) = enter_impl_trait(cx, |cx| {
// 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_body_id(cx, sig.decl.inputs, body_id); let args = match args {
FunctionArgs::Body(body_id) => {
clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id)
}
FunctionArgs::Names(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 mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
if sig.header.is_async() { if sig.header.is_async() {
decl.output = decl.sugared_async_return_type(); decl.output = decl.sugared_async_return_type();
@ -1051,18 +1063,12 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
), ),
hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)), hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, body); let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
MethodItem(m, None) MethodItem(m, None)
} }
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let (generics, decl) = enter_impl_trait(cx, |cx| { let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
// NOTE: generics must be cleaned before args TyMethodItem(m)
let generics = clean_generics(trait_item.generics, cx);
let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
let decl = clean_fn_decl_with_args(cx, sig.decl, args);
(generics, decl)
});
TyMethodItem(Box::new(Function { decl, generics }))
} }
hir::TraitItemKind::Type(bounds, Some(default)) => { hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
@ -1099,7 +1105,7 @@ pub(crate) fn clean_impl_item<'tcx>(
AssocConstItem(clean_ty(ty, cx), default) AssocConstItem(clean_ty(ty, cx), default)
} }
hir::ImplItemKind::Fn(ref sig, body) => { hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, body); let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
let defaultness = cx.tcx.impl_defaultness(impl_.owner_id); let defaultness = cx.tcx.impl_defaultness(impl_.owner_id);
MethodItem(m, Some(defaultness)) MethodItem(m, Some(defaultness))
} }

View file

@ -694,13 +694,10 @@ impl Item {
asyncness: hir::IsAsync::NotAsync, asyncness: hir::IsAsync::NotAsync,
} }
} }
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => { ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
let def_id = self.item_id.as_def_id().unwrap(); let def_id = self.item_id.as_def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id)) build_fn_header(def_id, tcx, tcx.asyncness(def_id))
} }
ItemKind::TyMethodItem(_) => {
build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
}
_ => return None, _ => return None,
}; };
Some(header) Some(header)

View file

@ -0,0 +1,14 @@
// edition:2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
pub trait Foo {
// @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn bar() -> i32"
async fn bar() -> i32;
// @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn baz() -> i32"
async fn baz() -> i32 {
1
}
}