rustdoc: Extend fake_variadic to "wrapped" tuples

This allows impls such as `impl QueryData for OneOf<(T,)>`
to be displayed as variadic: `impl QueryData for OneOf<(T₁, T₂, …, Tₙ)>`.

See question on zulip:
<https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Make.20.60.23.5Bdoc.28fake_variadic.29.5D.60.20more.20useful>
This commit is contained in:
Tau Gärtli 2024-10-24 18:50:55 +02:00
parent 8aca4bab08
commit 4e48768908
No known key found for this signature in database
3 changed files with 55 additions and 6 deletions

View File

@ -918,12 +918,7 @@ fn check_doc_fake_variadic(&self, meta: &MetaItemInner, hir_id: HirId) {
}; };
match item_kind { match item_kind {
Some(ItemKind::Impl(i)) => { Some(ItemKind::Impl(i)) => {
let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty)
|| if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
bare_fn_ty.decl.inputs.len() == 1
} else {
false
}
|| if let Some(&[hir::GenericArg::Type(ty)]) = i || if let Some(&[hir::GenericArg::Type(ty)]) = i
.of_trait .of_trait
.as_ref() .as_ref()
@ -2630,3 +2625,20 @@ fn check_duplicates(
}, },
} }
} }
fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool {
matches!(&self_ty.kind, hir::TyKind::Tup([_]))
|| if let hir::TyKind::BareFn(bare_fn_ty) = &self_ty.kind {
bare_fn_ty.decl.inputs.len() == 1
} else {
false
}
|| (if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &self_ty.kind
&& let Some(&[hir::GenericArg::Type(ty)]) =
path.segments.last().map(|last| last.args().args)
{
doc_fake_variadic_is_allowed_self_ty(ty)
} else {
false
})
}

View File

@ -1368,6 +1368,24 @@ fn print_type<'a, 'tcx: 'a>(
write!(f, " -> ")?; write!(f, " -> ")?;
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
} }
} else if let clean::Type::Path { path } = type_
&& let Some(generics) = path.generics()
&& generics.len() == 1
&& self.kind.is_fake_variadic()
{
let ty = generics[0];
let wrapper = anchor(path.def_id(), path.last(), cx);
if f.alternate() {
write!(f, "{wrapper:#}&lt;")?;
} else {
write!(f, "{wrapper}<")?;
}
self.print_type(ty, f, use_absolute, cx)?;
if f.alternate() {
write!(f, "&gt;")?;
} else {
write!(f, ">")?;
}
} else { } else {
fmt_type(&type_, f, use_absolute, cx)?; fmt_type(&type_, f, use_absolute, cx)?;
} }

View File

@ -33,3 +33,22 @@ pub trait Baz<T> { fn baz(&self) -> T { todo!() } }
//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)' //@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)'
#[doc(fake_variadic)] #[doc(fake_variadic)]
impl<T> Baz<T> for (T,) {} impl<T> Baz<T> for (T,) {}
pub trait Qux {}
pub struct NewType<T>(T);
//@ has foo/trait.Qux.html
//@ has - '//section[@id="impl-Qux-for-NewType%3C(T,)%3E"]/h3' 'impl<T> Qux for NewType<(T₁, T₂, …, Tₙ)>'
#[doc(fake_variadic)]
impl<T> Qux for NewType<(T,)> {}
//@ has foo/trait.Qux.html
//@ has - '//section[@id="impl-Qux-for-NewType%3CNewType%3C(T,)%3E%3E"]/h3' 'impl<T> Qux for NewType<NewType<(T₁, T₂, …, Tₙ)>>'
#[doc(fake_variadic)]
impl<T> Qux for NewType<NewType<(T,)>> {}
//@ has foo/trait.Qux.html
//@ has - '//section[@id="impl-Qux-for-NewType%3Cfn(T)+-%3E+Out%3E"]/h3' 'impl<T, Out> Qux for NewType<fn(T₁, T₂, …, Tₙ) -> Out>'
#[doc(fake_variadic)]
impl<T, Out> Qux for NewType<fn(T) -> Out> {}