From 4e487689085ba8b490fbf735163250cc4edb05ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Thu, 24 Oct 2024 18:50:55 +0200 Subject: [PATCH] rustdoc: Extend fake_variadic to "wrapped" tuples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: --- compiler/rustc_passes/src/check_attr.rs | 24 +++++++++++++++++------ src/librustdoc/html/format.rs | 18 +++++++++++++++++ tests/rustdoc/primitive-tuple-variadic.rs | 19 ++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 61e196bdebe66..62c502f952429 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -918,12 +918,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }; match item_kind { Some(ItemKind::Impl(i)) => { - let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) - || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind { - bare_fn_ty.decl.inputs.len() == 1 - } else { - false - } + let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty) || if let Some(&[hir::GenericArg::Type(ty)]) = i .of_trait .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 + }) +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5c599f20f9fdb..ea2f930ab8376 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1368,6 +1368,24 @@ impl clean::Impl { write!(f, " -> ")?; 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:#}<")?; + } else { + write!(f, "{wrapper}<")?; + } + self.print_type(ty, f, use_absolute, cx)?; + if f.alternate() { + write!(f, ">")?; + } else { + write!(f, ">")?; + } } else { fmt_type(&type_, f, use_absolute, cx)?; } diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index b15e996f929a9..d142729d2a8bc 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -33,3 +33,22 @@ impl Baz<[T; 1]> for (T,) {} //@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl Baz for (T₁, T₂, …, Tₙ)' #[doc(fake_variadic)] impl Baz for (T,) {} + +pub trait Qux {} + +pub struct NewType(T); + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3C(T,)%3E"]/h3' 'impl Qux for NewType<(T₁, T₂, …, Tₙ)>' +#[doc(fake_variadic)] +impl Qux for NewType<(T,)> {} + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3CNewType%3C(T,)%3E%3E"]/h3' 'impl Qux for NewType>' +#[doc(fake_variadic)] +impl Qux for NewType> {} + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3Cfn(T)+-%3E+Out%3E"]/h3' 'impl Qux for NewType Out>' +#[doc(fake_variadic)] +impl Qux for NewType Out> {}