Skip to content

Commit

Permalink
Rollup merge of rust-lang#103892 - compiler-errors:afit-rustdoc, r=Gu…
Browse files Browse the repository at this point in the history
…illaumeGomez

Properly render asyncness for trait fns without default body

We weren't properly desugaring async fns in traits unless they had default bodies (in which case rustdoc treats them much like they came from an impl).

cc ``@yoshuawuyts`` should help with https://rust-lang.zulipchat.com/#narrow/stream/330606-wg-async.2Fasync-fn-in-trait-impl/topic/type.20inside.20.60async.20fn.60.20body.20must.20be.20known.20in.20this.20context/near/306894869
  • Loading branch information
Dylan-DPC authored Nov 3, 2022
2 parents 4581550 + 59be515 commit 782afb6
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 18 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
/// Check if a function is async.
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
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.
Expand Down
32 changes: 19 additions & 13 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ fn clean_fn_or_proc_macro<'tcx>(
ProcMacroItem(ProcMacro { kind, helpers })
}
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);
FunctionItem(func)
}
Expand Down Expand Up @@ -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>(
cx: &mut DocContext<'tcx>,
sig: &hir::FnSig<'tcx>,
generics: &hir::Generics<'tcx>,
body_id: hir::BodyId,
args: FunctionArgs<'tcx>,
) -> Box<Function> {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
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);
if sig.header.is_async() {
decl.output = decl.sugared_async_return_type();
Expand Down Expand Up @@ -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::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)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
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 }))
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
TyMethodItem(m)
}
hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
Expand Down Expand Up @@ -1099,7 +1105,7 @@ pub(crate) fn clean_impl_item<'tcx>(
AssocConstItem(clean_ty(ty, cx), default)
}
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);
MethodItem(m, Some(defaultness))
}
Expand Down
5 changes: 1 addition & 4 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,13 +694,10 @@ impl Item {
asyncness: hir::IsAsync::NotAsync,
}
}
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
let def_id = self.item_id.as_def_id().unwrap();
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,
};
Some(header)
Expand Down
14 changes: 14 additions & 0 deletions src/test/rustdoc/async-trait-sig.rs
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 782afb6

Please sign in to comment.