From 9940ed08057bbee0b681beee02025169020c7519 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Jun 2022 11:23:06 -0700 Subject: [PATCH 01/19] docs: clean up trait docs for tuples --- library/core/src/fmt/mod.rs | 38 +++++++--- library/core/src/hash/mod.rs | 30 ++++++-- library/core/src/tuple.rs | 136 +++++++++++++++++++++-------------- 3 files changed, 132 insertions(+), 72 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 63655ae8a240b..46b2b0c92bf7a 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2313,23 +2313,39 @@ macro_rules! peel { macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized { - #[allow(non_snake_case, unused_assignments)] - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - let mut builder = f.debug_tuple(""); - let ($(ref $name,)+) = *self; - $( - builder.field(&$name); - )+ - - builder.finish() + maybe_tuple_doc! { + $($name)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[allow(non_snake_case, unused_assignments)] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut builder = f.debug_tuple(""); + let ($(ref $name,)+) = *self; + $( + builder.field(&$name); + )+ + + builder.finish() + } } } peel! { $($name,)+ } ) } +macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; +} + macro_rules! last_type { ($a:ident,) => { $a }; ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 3d168f62a09f5..ae3799d2a963c 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -883,18 +883,34 @@ mod impls { ); ( $($name:ident)+) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { - #[allow(non_snake_case)] - #[inline] - fn hash(&self, state: &mut S) { - let ($(ref $name,)+) = *self; - $($name.hash(state);)+ + maybe_tuple_doc! { + $($name)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[allow(non_snake_case)] + #[inline] + fn hash(&self, state: &mut S) { + let ($(ref $name,)+) = *self; + $($name.hash(state);)+ + } } } ); } + macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; + } + macro_rules! last_type { ($a:ident,) => { $a }; ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 181717f35bd25..61fa0eea78a73 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -19,75 +19,103 @@ macro_rules! tuple_impls { }; // "Private" internal implementation (@impl $( $T:ident )+) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialEq),+> PartialEq for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn eq(&self, other: &($($T,)+)) -> bool { - $( ${ignore(T)} self.${index()} == other.${index()} )&&+ - } - #[inline] - fn ne(&self, other: &($($T,)+)) -> bool { - $( ${ignore(T)} self.${index()} != other.${index()} )||+ + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T:PartialEq),+> PartialEq for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn eq(&self, other: &($($T,)+)) -> bool { + $( ${ignore(T)} self.${index()} == other.${index()} )&&+ + } + #[inline] + fn ne(&self, other: &($($T,)+)) -> bool { + $( ${ignore(T)} self.${index()} != other.${index()} )||+ + } } } - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Eq),+> Eq for ($($T,)+) - where - last_type!($($T,)+): ?Sized - {} + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T:Eq),+> Eq for ($($T,)+) + where + last_type!($($T,)+): ?Sized + {} + } - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn partial_cmp(&self, other: &($($T,)+)) -> Option { - lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn partial_cmp(&self, other: &($($T,)+)) -> Option { + lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn lt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn le(&self, other: &($($T,)+)) -> bool { + lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn ge(&self, other: &($($T,)+)) -> bool { + lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn gt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(gt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + } } } - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Ord),+> Ord for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn cmp(&self, other: &($($T,)+)) -> Ordering { - lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T:Ord),+> Ord for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn cmp(&self, other: &($($T,)+)) -> Ordering { + lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) + } } } - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Default),+> Default for ($($T,)+) { - #[inline] - fn default() -> ($($T,)+) { - ($({ let x: $T = Default::default(); x},)+) + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T:Default),+> Default for ($($T,)+) { + #[inline] + fn default() -> ($($T,)+) { + ($({ let x: $T = Default::default(); x},)+) + } } } } } +macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; +} + // Constructs an expression that performs a lexical ordering using method $rel. // The values are interleaved, so the macro invocation for // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, From 1e6a85789e866c725015e0e2a5defeccbcc2cc3b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Jun 2022 11:23:25 -0700 Subject: [PATCH 02/19] rustdoc: show auto/blanket docs for tuple and unit --- library/core/src/primitive_docs.rs | 10 ++++++++++ library/std/src/primitive_docs.rs | 10 ++++++++++ src/test/rustdoc/primitive-tuple-auto-trait.rs | 14 ++++++++++++++ src/test/rustdoc/primitive-unit-auto-trait.rs | 14 ++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 src/test/rustdoc/primitive-tuple-auto-trait.rs create mode 100644 src/test/rustdoc/primitive-unit-auto-trait.rs diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 688ab63bf1366..06e2a0eb2de3f 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -439,6 +439,11 @@ mod prim_char {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_unit {} +// Required to make auto trait impls render. +// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl () {} + #[doc(primitive = "pointer")] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -949,6 +954,11 @@ mod prim_str {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_tuple {} +// Required to make auto trait impls render. +// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl (T, U) {} + #[doc(primitive = "f32")] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 688ab63bf1366..06e2a0eb2de3f 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -439,6 +439,11 @@ mod prim_char {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_unit {} +// Required to make auto trait impls render. +// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl () {} + #[doc(primitive = "pointer")] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -949,6 +954,11 @@ mod prim_str {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_tuple {} +// Required to make auto trait impls render. +// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl (T, U) {} + #[doc(primitive = "f32")] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// diff --git a/src/test/rustdoc/primitive-tuple-auto-trait.rs b/src/test/rustdoc/primitive-tuple-auto-trait.rs new file mode 100644 index 0000000000000..249ff1b20e35f --- /dev/null +++ b/src/test/rustdoc/primitive-tuple-auto-trait.rs @@ -0,0 +1,14 @@ +// compile-flags: --crate-type lib --edition 2018 + +#![crate_name = "foo"] +#![feature(rustdoc_internals)] + +// @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple' +// @has - '//span[@class="in-band"]' 'Primitive Type tuple' +// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' +// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Sync' +#[doc(primitive = "tuple")] +/// this is a test! +mod tuple_prim {} diff --git a/src/test/rustdoc/primitive-unit-auto-trait.rs b/src/test/rustdoc/primitive-unit-auto-trait.rs new file mode 100644 index 0000000000000..76182622ef5fb --- /dev/null +++ b/src/test/rustdoc/primitive-unit-auto-trait.rs @@ -0,0 +1,14 @@ +// compile-flags: --crate-type lib --edition 2018 + +#![crate_name = "foo"] +#![feature(rustdoc_internals)] + +// @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit' +// @has - '//span[@class="in-band"]' 'Primitive Type unit' +// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' +// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for ()' +#[doc(primitive = "unit")] +/// this is a test! +mod unit_prim {} From 7a935670055d87e17c381542f4eaab481e8bf17b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Jun 2022 12:12:49 -0700 Subject: [PATCH 03/19] docs: show Clone and Copy on () doc pages --- library/core/src/clone.rs | 1 - library/core/src/marker.rs | 1 - library/core/src/primitive_docs.rs | 34 ++++++++++++++++++++++++++++++ library/std/src/primitive_docs.rs | 34 ++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 70f3fe853d97a..fd5624812f554 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -95,7 +95,6 @@ use crate::marker::Destruct; /// /// * Function item types (i.e., the distinct types defined for each function) /// * Function pointer types (e.g., `fn() -> i32`) -/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Clone` themselves. /// Note that variables captured by shared reference always implement `Clone` diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4a90ef9545d68..2c57897956fcd 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -359,7 +359,6 @@ pub trait StructuralEq { /// /// * Function item types (i.e., the distinct types defined for each function) /// * Function pointer types (e.g., `fn() -> i32`) -/// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Copy` themselves. /// Note that variables captured by shared reference always implement `Copy` diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 06e2a0eb2de3f..db2f7ec0e0e35 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -444,6 +444,22 @@ mod prim_unit {} #[doc(hidden)] impl () {} +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for () { + fn clone(&self) -> Self { + loop {} + } +} + +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for () { + // empty +} + #[doc(primitive = "pointer")] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -959,6 +975,24 @@ mod prim_tuple {} #[doc(hidden)] impl (T, U) {} +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +/// This trait is implemented on arbitrary-length tuples. +impl Clone for (T,) { + fn clone(&self) -> Self { + loop {} + } +} + +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +/// This trait is implemented on arbitrary-length tuples. +impl Copy for (T,) { + // empty +} + #[doc(primitive = "f32")] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 06e2a0eb2de3f..db2f7ec0e0e35 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -444,6 +444,22 @@ mod prim_unit {} #[doc(hidden)] impl () {} +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for () { + fn clone(&self) -> Self { + loop {} + } +} + +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for () { + // empty +} + #[doc(primitive = "pointer")] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -959,6 +975,24 @@ mod prim_tuple {} #[doc(hidden)] impl (T, U) {} +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +/// This trait is implemented on arbitrary-length tuples. +impl Clone for (T,) { + fn clone(&self) -> Self { + loop {} + } +} + +// Fake impl that's only really used for docs. +#[cfg(doc)] +#[stable(feature = "rust1", since = "1.0.0")] +/// This trait is implemented on arbitrary-length tuples. +impl Copy for (T,) { + // empty +} + #[doc(primitive = "f32")] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// From 6950f144cf83d10bc4a304b48488f9f5368cfaae Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 8 Jun 2022 19:26:51 -0700 Subject: [PATCH 04/19] rustdoc: show tuple impls as `impl Trait for (T, ...)` This commit adds a new unstable attribute, `#[doc(tuple_varadic)]`, that shows a 1-tuple as `(T, ...)` instead of just `(T,)`, and links to a section in the tuple primitive docs that talks about these. --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 +++ compiler/rustc_passes/src/check_attr.rs | 41 ++++++++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/fmt/mod.rs | 1 + library/core/src/hash/mod.rs | 1 + library/core/src/primitive_docs.rs | 25 ++++------- library/core/src/tuple.rs | 1 + library/std/src/primitive_docs.rs | 25 ++++------- src/librustdoc/clean/inline.rs | 6 ++- src/librustdoc/clean/mod.rs | 6 ++- src/librustdoc/clean/types.rs | 5 +++ src/librustdoc/html/format.rs | 20 +++++++-- src/librustdoc/json/conversions.rs | 2 +- .../feature-gate-rustdoc_internals.rs | 5 +++ .../feature-gate-rustdoc_internals.stderr | 11 ++++- 15 files changed, 111 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 77dd4ccd64ef2..1777438d304ea 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -401,6 +401,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { let msg = "`#[doc(keyword)]` is meant for internal use only"; gate_feature_post!(self, rustdoc_internals, attr.span, msg); } + + if nested_meta.has_name(sym::tuple_varadic) { + let msg = "`#[doc(tuple_varadic)]` is meant for internal use only"; + gate_feature_post!(self, rustdoc_internals, attr.span, msg); + } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5cc97d326d3d8..ea8c1b45a60a7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -804,6 +804,37 @@ impl CheckAttrVisitor<'_> { true } + fn check_doc_tuple_varadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { + match self.tcx.hir().find(hir_id).and_then(|node| match node { + hir::Node::Item(item) => Some(&item.kind), + _ => None, + }) { + Some(ItemKind::Impl(ref i)) => { + if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) { + self.tcx + .sess + .struct_span_err( + meta.span(), + "`#[doc(tuple_varadic)]` can only be used on unary tuples", + ) + .emit(); + return false; + } + } + _ => { + self.tcx + .sess + .struct_span_err( + meta.span(), + "`#[doc(keyword = \"...\")]` can only be used on impl blocks", + ) + .emit(); + return false; + } + } + true + } + /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. Returns `true` if valid. /// /// A doc inlining attribute is invalid if it is applied to a non-`use` item, or @@ -1064,6 +1095,13 @@ impl CheckAttrVisitor<'_> { is_valid = false } + sym::tuple_varadic + if !self.check_attr_not_crate_level(meta, hir_id, "tuple_varadic") + || !self.check_doc_tuple_varadic(meta, hir_id) => + { + is_valid = false + } + sym::html_favicon_url | sym::html_logo_url | sym::html_playground_url @@ -1117,7 +1155,8 @@ impl CheckAttrVisitor<'_> { | sym::no_inline | sym::notable_trait | sym::passes - | sym::plugins => {} + | sym::plugins + | sym::tuple_varadic => {} sym::test => { if !self.check_test_attr(meta, hir_id) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bcaf53639cc63..37e905f7f562b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1439,6 +1439,7 @@ symbols! { tuple, tuple_from_req, tuple_indexing, + tuple_varadic, two_phase, ty, type_alias_enum_variants, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 46b2b0c92bf7a..6c76e1488397c 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2335,6 +2335,7 @@ macro_rules! tuple { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { + #[cfg_attr(not(bootstrap), doc(tuple_varadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index ae3799d2a963c..d79258d2ed99a 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -900,6 +900,7 @@ mod impls { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { + #[cfg_attr(not(bootstrap), doc(tuple_varadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index db2f7ec0e0e35..26f9528dd22ee 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -916,24 +916,11 @@ mod prim_str {} /// /// # Trait implementations /// -/// If every type inside a tuple implements one of the following traits, then a -/// tuple itself also implements it. -/// -/// * [`Clone`] -/// * [`Copy`] -/// * [`PartialEq`] -/// * [`Eq`] -/// * [`PartialOrd`] -/// * [`Ord`] -/// * [`Debug`] -/// * [`Default`] -/// * [`Hash`] -/// -/// [`Debug`]: fmt::Debug -/// [`Hash`]: hash::Hash -/// -/// Due to a temporary restriction in Rust's type system, these traits are only -/// implemented on tuples of arity 12 or less. In the future, this may change. +/// In this documentation the shorthand `(T, ...)` is used to represent all +/// tuples up to length twelve. When that is used, any trait bounds expressed +/// on `T` applies to each field of the tuple independently. Note that this is +/// a convenience notation to avoid repetitive documentation, not valid +/// Rust syntax. /// /// # Examples /// @@ -978,6 +965,7 @@ impl (T, U) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(tuple_varadic)] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -988,6 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(tuple_varadic)] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 61fa0eea78a73..9ddefc651baab 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -105,6 +105,7 @@ macro_rules! tuple_impls { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { + #[cfg_attr(not(bootstrap), doc(tuple_varadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index db2f7ec0e0e35..26f9528dd22ee 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -916,24 +916,11 @@ mod prim_str {} /// /// # Trait implementations /// -/// If every type inside a tuple implements one of the following traits, then a -/// tuple itself also implements it. -/// -/// * [`Clone`] -/// * [`Copy`] -/// * [`PartialEq`] -/// * [`Eq`] -/// * [`PartialOrd`] -/// * [`Ord`] -/// * [`Debug`] -/// * [`Default`] -/// * [`Hash`] -/// -/// [`Debug`]: fmt::Debug -/// [`Hash`]: hash::Hash -/// -/// Due to a temporary restriction in Rust's type system, these traits are only -/// implemented on tuples of arity 12 or less. In the future, this may change. +/// In this documentation the shorthand `(T, ...)` is used to represent all +/// tuples up to length twelve. When that is used, any trait bounds expressed +/// on `T` applies to each field of the tuple independently. Note that this is +/// a convenience notation to avoid repetitive documentation, not valid +/// Rust syntax. /// /// # Examples /// @@ -978,6 +965,7 @@ impl (T, U) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(tuple_varadic)] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -988,6 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(tuple_varadic)] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a82abe6692655..d8f6a9c3ff07c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -500,7 +500,11 @@ pub(crate) fn build_impl( for_, items: trait_items, polarity, - kind: ImplKind::Normal, + kind: if utils::has_doc_flag(tcx, did, sym::tuple_varadic) { + ImplKind::TupleVaradic + } else { + ImplKind::Normal + }, }), box merged_attrs, cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f3070fb35f1d0..b15ef424cb644 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1999,7 +1999,11 @@ fn clean_impl<'tcx>( for_, items, polarity: tcx.impl_polarity(def_id), - kind: ImplKind::Normal, + kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_varadic) { + ImplKind::TupleVaradic + } else { + ImplKind::Normal + }, }); Item::from_hir_id_and_parts(hir_id, None, kind, cx) }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 4605793d0df94..95c84e68b8336 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2394,6 +2394,7 @@ impl Impl { pub(crate) enum ImplKind { Normal, Auto, + TupleVaradic, Blanket(Box), } @@ -2406,6 +2407,10 @@ impl ImplKind { matches!(self, ImplKind::Blanket(_)) } + pub(crate) fn is_tuple_varadic(&self) -> bool { + matches!(self, ImplKind::TupleVaradic) + } + pub(crate) fn as_blanket_ty(&self) -> Option<&Type> { match self { ImplKind::Blanket(ty) => Some(ty), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b7789493df647..2f433c2313b74 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -713,6 +713,16 @@ fn primitive_link( prim: clean::PrimitiveType, name: &str, cx: &Context<'_>, +) -> fmt::Result { + primitive_link_fragment(f, prim, name, "", cx) +} + +fn primitive_link_fragment( + f: &mut fmt::Formatter<'_>, + prim: clean::PrimitiveType, + name: &str, + fragment: &str, + cx: &Context<'_>, ) -> fmt::Result { let m = &cx.cache(); let mut needs_termination = false; @@ -723,7 +733,7 @@ fn primitive_link( let len = if len == 0 { 0 } else { len - 1 }; write!( f, - "", + "", "../".repeat(len), prim.as_sym() )?; @@ -754,7 +764,7 @@ fn primitive_link( }; if let Some(mut loc) = loc { loc.push_fmt(format_args!("primitive.{}.html", prim.as_sym())); - write!(f, "", loc.finish())?; + write!(f, "", loc.finish())?; needs_termination = true; } } @@ -1064,7 +1074,11 @@ impl clean::Impl { write!(f, " for ")?; } - if let Some(ty) = self.kind.as_blanket_ty() { + if let clean::Type::Tuple(types) = &self.for_ && + let [clean::Type::Generic(name)] = &types[..] && + (self.kind.is_tuple_varadic() || self.kind.is_auto()) { + primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}, ...)"), "#trait-implementations-1", cx)?; + } else if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { fmt_type(&self.for_, f, use_absolute, cx)?; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 51a2abc50bc2b..4fde63c99d4b9 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -552,7 +552,7 @@ impl FromWithTcx for Impl { let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx)); // FIXME: use something like ImplKind in JSON? let (synthetic, blanket_impl) = match kind { - clean::ImplKind::Normal => (false, None), + clean::ImplKind::Normal | clean::ImplKind::TupleVaradic => (false, None), clean::ImplKind::Auto => (true, None), clean::ImplKind::Blanket(ty) => (false, Some(*ty)), }; diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs index d2ff4f6200986..e40a3044b9469 100644 --- a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -2,4 +2,9 @@ /// wonderful mod foo {} +trait Mine {} + +#[doc(tuple_varadic)] //~ ERROR: `#[doc(tuple_varadic)]` is meant for internal use only +impl Mine for (T,) {} + fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr index e96461ac38acb..00dab359e7350 100644 --- a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -7,6 +7,15 @@ LL | #[doc(keyword = "match")] = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: `#[doc(tuple_varadic)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:7:1 + | +LL | #[doc(tuple_varadic)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From 85b0c2ffbb2c047c744ad10f7e72d87cbf4dbd32 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 8 Jun 2022 19:51:54 -0700 Subject: [PATCH 05/19] rustdoc: fixed messed-up rustdoc auto trait impls Before: impl UnwindSafe for (T, ...) where T: UnwindSafe, U: UnwindSafe, After: impl UnwindSafe for (T, ...) where T: UnwindSafe, --- library/core/src/primitive_docs.rs | 2 +- library/std/src/primitive_docs.rs | 2 +- src/librustdoc/clean/types.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 26f9528dd22ee..6fa9e795db81b 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -960,7 +960,7 @@ mod prim_tuple {} // Required to make auto trait impls render. // See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] -impl (T, U) {} +impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 26f9528dd22ee..6fa9e795db81b 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -960,7 +960,7 @@ mod prim_tuple {} // Required to make auto trait impls render. // See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] -impl (T, U) {} +impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 95c84e68b8336..f77884370f55a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1750,7 +1750,7 @@ pub(crate) enum PrimitiveType { Never, } -type SimplifiedTypes = FxHashMap>; +type SimplifiedTypes = FxHashMap>; impl PrimitiveType { pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType { use ast::{FloatTy, IntTy, UintTy}; @@ -1839,10 +1839,10 @@ impl PrimitiveType { // // Either manually update this arrayvec at this point // or start with a more complex refactoring. - Tuple => [TupleSimplifiedType(2), TupleSimplifiedType(3)].into(), + Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(), Unit => single(TupleSimplifiedType(0)), - RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into(), - Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into(), + RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(), + Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(), // FIXME: This will be wrong if we ever add inherent impls // for function pointers. Fn => ArrayVec::new(), From 9f6dcceef0bf2f455c29e8863413604b58e2b6b5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 8 Jun 2022 20:06:54 -0700 Subject: [PATCH 06/19] Fix bootstrap attr --- library/core/src/primitive_docs.rs | 4 ++-- library/std/src/primitive_docs.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 6fa9e795db81b..510d47f4e702d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -965,7 +965,7 @@ impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[doc(tuple_varadic)] +#[cfg_attr(not(bootstrap), doc(tuple_varadic))] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -976,7 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[doc(tuple_varadic)] +#[cfg_attr(not(bootstrap), doc(tuple_varadic))] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 6fa9e795db81b..510d47f4e702d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -965,7 +965,7 @@ impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[doc(tuple_varadic)] +#[cfg_attr(not(bootstrap), doc(tuple_varadic))] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -976,7 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[doc(tuple_varadic)] +#[cfg_attr(not(bootstrap), doc(tuple_varadic))] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty From 9b31323b8f784ebb8689bb11489caefadb552f60 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 08:30:46 -0700 Subject: [PATCH 07/19] Fix incorrectly spelled "variadic" --- compiler/rustc_ast_passes/src/feature_gate.rs | 4 ++-- compiler/rustc_passes/src/check_attr.rs | 12 ++++++------ compiler/rustc_span/src/symbol.rs | 2 +- library/core/src/fmt/mod.rs | 2 +- library/core/src/hash/mod.rs | 2 +- library/core/src/primitive_docs.rs | 4 ++-- library/core/src/tuple.rs | 2 +- library/std/src/primitive_docs.rs | 4 ++-- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/format.rs | 2 +- .../feature-gates/feature-gate-rustdoc_internals.rs | 2 +- .../feature-gate-rustdoc_internals.stderr | 4 ++-- 14 files changed, 23 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1777438d304ea..258692a982cf7 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -402,8 +402,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(self, rustdoc_internals, attr.span, msg); } - if nested_meta.has_name(sym::tuple_varadic) { - let msg = "`#[doc(tuple_varadic)]` is meant for internal use only"; + if nested_meta.has_name(sym::tuple_variadic) { + let msg = "`#[doc(tuple_variadic)]` is meant for internal use only"; gate_feature_post!(self, rustdoc_internals, attr.span, msg); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ea8c1b45a60a7..7de5cb2683a9a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -804,7 +804,7 @@ impl CheckAttrVisitor<'_> { true } - fn check_doc_tuple_varadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { + fn check_doc_tuple_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { match self.tcx.hir().find(hir_id).and_then(|node| match node { hir::Node::Item(item) => Some(&item.kind), _ => None, @@ -815,7 +815,7 @@ impl CheckAttrVisitor<'_> { .sess .struct_span_err( meta.span(), - "`#[doc(tuple_varadic)]` can only be used on unary tuples", + "`#[doc(tuple_variadic)]` can only be used on unary tuples", ) .emit(); return false; @@ -1095,9 +1095,9 @@ impl CheckAttrVisitor<'_> { is_valid = false } - sym::tuple_varadic - if !self.check_attr_not_crate_level(meta, hir_id, "tuple_varadic") - || !self.check_doc_tuple_varadic(meta, hir_id) => + sym::tuple_variadic + if !self.check_attr_not_crate_level(meta, hir_id, "tuple_variadic") + || !self.check_doc_tuple_variadic(meta, hir_id) => { is_valid = false } @@ -1156,7 +1156,7 @@ impl CheckAttrVisitor<'_> { | sym::notable_trait | sym::passes | sym::plugins - | sym::tuple_varadic => {} + | sym::tuple_variadic => {} sym::test => { if !self.check_test_attr(meta, hir_id) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 37e905f7f562b..ce3efc036ae8e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1439,7 +1439,7 @@ symbols! { tuple, tuple_from_req, tuple_indexing, - tuple_varadic, + tuple_variadic, two_phase, ty, type_alias_enum_variants, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6c76e1488397c..5a9370a88eca0 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2335,7 +2335,7 @@ macro_rules! tuple { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_varadic))] + #[cfg_attr(not(bootstrap), doc(tuple_variadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index d79258d2ed99a..9a4c877b2d36b 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -900,7 +900,7 @@ mod impls { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_varadic))] + #[cfg_attr(not(bootstrap), doc(tuple_variadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 510d47f4e702d..bf4431c4958e9 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -965,7 +965,7 @@ impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_varadic))] +#[cfg_attr(not(bootstrap), doc(tuple_variadic))] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -976,7 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_varadic))] +#[cfg_attr(not(bootstrap), doc(tuple_variadic))] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 9ddefc651baab..c6e3d045a78d3 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -105,7 +105,7 @@ macro_rules! tuple_impls { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_varadic))] + #[cfg_attr(not(bootstrap), doc(tuple_variadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 510d47f4e702d..bf4431c4958e9 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -965,7 +965,7 @@ impl (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_varadic))] +#[cfg_attr(not(bootstrap), doc(tuple_variadic))] /// This trait is implemented on arbitrary-length tuples. impl Clone for (T,) { fn clone(&self) -> Self { @@ -976,7 +976,7 @@ impl Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_varadic))] +#[cfg_attr(not(bootstrap), doc(tuple_variadic))] /// This trait is implemented on arbitrary-length tuples. impl Copy for (T,) { // empty diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d8f6a9c3ff07c..d4c38f34b5b11 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -500,7 +500,7 @@ pub(crate) fn build_impl( for_, items: trait_items, polarity, - kind: if utils::has_doc_flag(tcx, did, sym::tuple_varadic) { + kind: if utils::has_doc_flag(tcx, did, sym::tuple_variadic) { ImplKind::TupleVaradic } else { ImplKind::Normal diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b15ef424cb644..fd30691c32489 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1999,7 +1999,7 @@ fn clean_impl<'tcx>( for_, items, polarity: tcx.impl_polarity(def_id), - kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_varadic) { + kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_variadic) { ImplKind::TupleVaradic } else { ImplKind::Normal diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f77884370f55a..83ab9acd3005a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2407,7 +2407,7 @@ impl ImplKind { matches!(self, ImplKind::Blanket(_)) } - pub(crate) fn is_tuple_varadic(&self) -> bool { + pub(crate) fn is_tuple_variadic(&self) -> bool { matches!(self, ImplKind::TupleVaradic) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2f433c2313b74..69bd0744a1096 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1076,7 +1076,7 @@ impl clean::Impl { if let clean::Type::Tuple(types) = &self.for_ && let [clean::Type::Generic(name)] = &types[..] && - (self.kind.is_tuple_varadic() || self.kind.is_auto()) { + (self.kind.is_tuple_variadic() || self.kind.is_auto()) { primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}, ...)"), "#trait-implementations-1", cx)?; } else if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs index e40a3044b9469..6a144412d0751 100644 --- a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -4,7 +4,7 @@ mod foo {} trait Mine {} -#[doc(tuple_varadic)] //~ ERROR: `#[doc(tuple_varadic)]` is meant for internal use only +#[doc(tuple_variadic)] //~ ERROR: `#[doc(tuple_variadic)]` is meant for internal use only impl Mine for (T,) {} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr index 00dab359e7350..2b1c790e80c17 100644 --- a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -7,10 +7,10 @@ LL | #[doc(keyword = "match")] = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable -error[E0658]: `#[doc(tuple_varadic)]` is meant for internal use only +error[E0658]: `#[doc(tuple_variadic)]` is meant for internal use only --> $DIR/feature-gate-rustdoc_internals.rs:7:1 | -LL | #[doc(tuple_varadic)] +LL | #[doc(tuple_variadic)] | ^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #90418 for more information From 090c68ba5c06ebfb9c94e5ba8d99279029ea9401 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 08:33:39 -0700 Subject: [PATCH 08/19] Use relative path for addressing things in rust-lang/rust Co-authored-by: Jacob Hoffman-Andrews --- library/core/src/primitive_docs.rs | 4 ++-- library/std/src/primitive_docs.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bf4431c4958e9..a02c54c07bc9d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -440,7 +440,7 @@ mod prim_char {} mod prim_unit {} // Required to make auto trait impls render. -// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl () {} @@ -958,7 +958,7 @@ mod prim_str {} mod prim_tuple {} // Required to make auto trait impls render. -// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl (T,) {} diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index bf4431c4958e9..a02c54c07bc9d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -440,7 +440,7 @@ mod prim_char {} mod prim_unit {} // Required to make auto trait impls render. -// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl () {} @@ -958,7 +958,7 @@ mod prim_str {} mod prim_tuple {} // Required to make auto trait impls render. -// See /src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl (T,) {} From 3fd16648fe7c7373965d9a14bc8c832589518361 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 09:29:06 -0700 Subject: [PATCH 09/19] Re-add explicit list of traits to tuple docs, with limit notes --- library/core/src/primitive_docs.rs | 39 ++++++++++++++++++++++++++---- library/std/src/primitive_docs.rs | 39 ++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index a02c54c07bc9d..be3953692fa31 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -916,11 +916,40 @@ mod prim_str {} /// /// # Trait implementations /// -/// In this documentation the shorthand `(T, ...)` is used to represent all -/// tuples up to length twelve. When that is used, any trait bounds expressed -/// on `T` applies to each field of the tuple independently. Note that this is -/// a convenience notation to avoid repetitive documentation, not valid -/// Rust syntax. +/// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. +/// When that is used, any trait bounds expressed on `T` applies to each field of the tuple +/// independently. Note that this is a convenience notation to avoid repetitive documentation, +/// not valid Rust syntax. +/// +/// Due to a temporary restriction in Rust’s type system, the following traits are only +/// implemented on tuples of arity 12 or less. In the future, this may change: +/// +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Debug`] +/// * [`Default`] +/// * [`Hash`] +/// +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// +/// The following traits are implemented for tuples of any length. These traits have +/// implementations that are automatically generated by the compiler, so are not limited by +/// missing language features. +/// +/// * [`Clone`] +/// * [`Copy`] +/// * [`Send`] +/// * [`Sync`] +/// * [`Unpin`] +/// * [`UnwindSafe`] +/// * [`RefUnwindSafe`] +/// +/// [`Unpin`]: marker::Unpin +/// [`UnwindSafe`]: panic::UnwindSafe +/// [`RefUnwindSafe`]: panic::RefUnwindSafe /// /// # Examples /// diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index a02c54c07bc9d..be3953692fa31 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -916,11 +916,40 @@ mod prim_str {} /// /// # Trait implementations /// -/// In this documentation the shorthand `(T, ...)` is used to represent all -/// tuples up to length twelve. When that is used, any trait bounds expressed -/// on `T` applies to each field of the tuple independently. Note that this is -/// a convenience notation to avoid repetitive documentation, not valid -/// Rust syntax. +/// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. +/// When that is used, any trait bounds expressed on `T` applies to each field of the tuple +/// independently. Note that this is a convenience notation to avoid repetitive documentation, +/// not valid Rust syntax. +/// +/// Due to a temporary restriction in Rust’s type system, the following traits are only +/// implemented on tuples of arity 12 or less. In the future, this may change: +/// +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Debug`] +/// * [`Default`] +/// * [`Hash`] +/// +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// +/// The following traits are implemented for tuples of any length. These traits have +/// implementations that are automatically generated by the compiler, so are not limited by +/// missing language features. +/// +/// * [`Clone`] +/// * [`Copy`] +/// * [`Send`] +/// * [`Sync`] +/// * [`Unpin`] +/// * [`UnwindSafe`] +/// * [`RefUnwindSafe`] +/// +/// [`Unpin`]: marker::Unpin +/// [`UnwindSafe`]: panic::UnwindSafe +/// [`RefUnwindSafe`]: panic::RefUnwindSafe /// /// # Examples /// From c1487550ca75c2bcd4cb4da038ef1d18d86a857a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 09:37:40 -0700 Subject: [PATCH 10/19] Add test case for #trait-implementations-1 link --- library/core/src/primitive_docs.rs | 2 ++ library/std/src/primitive_docs.rs | 2 ++ src/librustdoc/html/format.rs | 2 ++ src/test/rustdoc/primitive-tuple-auto-trait.rs | 8 ++++++++ 4 files changed, 14 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index be3953692fa31..c423acd7047de 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -914,6 +914,8 @@ mod prim_str {} /// /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). /// +// Hardcoded anchor in src/librustdoc/html/format.rs +// linked to as `#trait-implementations-1` /// # Trait implementations /// /// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index be3953692fa31..c423acd7047de 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -914,6 +914,8 @@ mod prim_str {} /// /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). /// +// Hardcoded anchor in src/librustdoc/html/format.rs +// linked to as `#trait-implementations-1` /// # Trait implementations /// /// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 69bd0744a1096..c714549d0f545 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1077,6 +1077,8 @@ impl clean::Impl { if let clean::Type::Tuple(types) = &self.for_ && let [clean::Type::Generic(name)] = &types[..] && (self.kind.is_tuple_variadic() || self.kind.is_auto()) { + // Hardcoded anchor library/core/src/primitive_docs.rs + // Link should match `# Trait implementations` primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}, ...)"), "#trait-implementations-1", cx)?; } else if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; diff --git a/src/test/rustdoc/primitive-tuple-auto-trait.rs b/src/test/rustdoc/primitive-tuple-auto-trait.rs index 249ff1b20e35f..71b0b07700958 100644 --- a/src/test/rustdoc/primitive-tuple-auto-trait.rs +++ b/src/test/rustdoc/primitive-tuple-auto-trait.rs @@ -11,4 +11,12 @@ // @has - '//div[@id="synthetic-implementations-list"]//h3' 'Sync' #[doc(primitive = "tuple")] /// this is a test! +/// +// Hardcoded anchor to header written in library/core/src/primitive_docs.rs +// @has - '//h2[@id="trait-implementations-1"]' 'Trait implementations' +/// # Trait implementations +/// +/// This header is hard-coded in the HTML format linking for `#[doc(tuple_variadics)]`. +/// To make sure it gets linked correctly, we need to make sure the hardcoded anchor +/// in the code matches what rustdoc generates for the header. mod tuple_prim {} From 26f04ebfa96aaaef4358e32a01b6ba0d0aa84835 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 10:14:10 -0700 Subject: [PATCH 11/19] Fix broken test case --- src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr index 2b1c790e80c17..9fe08afd4f05e 100644 --- a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -11,7 +11,7 @@ error[E0658]: `#[doc(tuple_variadic)]` is meant for internal use only --> $DIR/feature-gate-rustdoc_internals.rs:7:1 | LL | #[doc(tuple_variadic)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable From 28bd1a4847ab2f016e0b191a1dbd15b48675e84d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 10:32:39 -0700 Subject: [PATCH 12/19] docs: make all the variadic impls use `(T, ...)` exactly --- library/core/src/fmt/mod.rs | 2 +- library/core/src/hash/mod.rs | 24 ++++++++++++------------ library/core/src/tuple.rs | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 5a9370a88eca0..1c66089fad6e6 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2352,7 +2352,7 @@ macro_rules! last_type { ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; } -tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } +tuple! { E, D, C, B, A, Z, Y, X, W, V, U, T, } #[stable(feature = "rust1", since = "1.0.0")] impl Debug for [T] { diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 9a4c877b2d36b..2c152fe1b2c18 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -918,18 +918,18 @@ mod impls { } impl_hash_tuple! {} - impl_hash_tuple! { A } - impl_hash_tuple! { A B } - impl_hash_tuple! { A B C } - impl_hash_tuple! { A B C D } - impl_hash_tuple! { A B C D E } - impl_hash_tuple! { A B C D E F } - impl_hash_tuple! { A B C D E F G } - impl_hash_tuple! { A B C D E F G H } - impl_hash_tuple! { A B C D E F G H I } - impl_hash_tuple! { A B C D E F G H I J } - impl_hash_tuple! { A B C D E F G H I J K } - impl_hash_tuple! { A B C D E F G H I J K L } + impl_hash_tuple! { T } + impl_hash_tuple! { T B } + impl_hash_tuple! { T B C } + impl_hash_tuple! { T B C D } + impl_hash_tuple! { T B C D E } + impl_hash_tuple! { T B C D E F } + impl_hash_tuple! { T B C D E F G } + impl_hash_tuple! { T B C D E F G H } + impl_hash_tuple! { T B C D E F G H I } + impl_hash_tuple! { T B C D E F G H I J } + impl_hash_tuple! { T B C D E F G H I J K } + impl_hash_tuple! { T B C D E F G H I J K L } #[stable(feature = "rust1", since = "1.0.0")] impl Hash for [T] { diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index c6e3d045a78d3..d0d8c5faa4484 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -154,4 +154,4 @@ macro_rules! last_type { ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; } -tuple_impls!(A B C D E F G H I J K L); +tuple_impls!(E D C B A Z Y X W V U T); From 80b201da7d2b53024d595403809906b9205809e2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 20:07:10 -0700 Subject: [PATCH 13/19] Update library/std/src/primitive_docs.rs Co-authored-by: Jacob Hoffman-Andrews --- library/std/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index c423acd7047de..a19840ac57639 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -919,7 +919,7 @@ mod prim_str {} /// # Trait implementations /// /// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. -/// When that is used, any trait bounds expressed on `T` applies to each field of the tuple +/// When that is used, any trait bound expressed on `T` applies to each element of the tuple /// independently. Note that this is a convenience notation to avoid repetitive documentation, /// not valid Rust syntax. /// From 22c39aa8355483796317dfa456b58e5a4be114ef Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 21:45:23 -0700 Subject: [PATCH 14/19] Update library/core/src/primitive_docs.rs --- library/core/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index c423acd7047de..a19840ac57639 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -919,7 +919,7 @@ mod prim_str {} /// # Trait implementations /// /// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. -/// When that is used, any trait bounds expressed on `T` applies to each field of the tuple +/// When that is used, any trait bound expressed on `T` applies to each element of the tuple /// independently. Note that this is a convenience notation to avoid repetitive documentation, /// not valid Rust syntax. /// From 36fb094d253d3364482570613635a467fab851cb Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 11 Jun 2022 21:47:03 -0700 Subject: [PATCH 15/19] Add docs to `maybe_tuple_doc!` --- library/core/src/tuple.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index d0d8c5faa4484..ab3763cbc4196 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -103,6 +103,8 @@ macro_rules! tuple_impls { } } +// If this is a unary tuple, it adds a doc comment. +// Otherwise, it hides the docs entirely. macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { #[cfg_attr(not(bootstrap), doc(tuple_variadic))] From 95ae4c9295ccee95599de847fdaccb8cf123c219 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 12 Jun 2022 13:49:42 -0700 Subject: [PATCH 16/19] rustdoc: change error message for invalid `#[doc(tuple_variadic)]` Add test case. --- compiler/rustc_passes/src/check_attr.rs | 2 +- src/test/rustdoc-ui/tuple-variadic-check.rs | 15 +++++++++++++++ src/test/rustdoc-ui/tuple-variadic-check.stderr | 8 ++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/tuple-variadic-check.rs create mode 100644 src/test/rustdoc-ui/tuple-variadic-check.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7de5cb2683a9a..93b2c14129ed7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -815,7 +815,7 @@ impl CheckAttrVisitor<'_> { .sess .struct_span_err( meta.span(), - "`#[doc(tuple_variadic)]` can only be used on unary tuples", + "`#[doc(tuple_variadic)]` must used on the first of a set of tuple trait impls with varying arity", ) .emit(); return false; diff --git a/src/test/rustdoc-ui/tuple-variadic-check.rs b/src/test/rustdoc-ui/tuple-variadic-check.rs new file mode 100644 index 0000000000000..11ce2dbe28050 --- /dev/null +++ b/src/test/rustdoc-ui/tuple-variadic-check.rs @@ -0,0 +1,15 @@ +#![feature(rustdoc_internals)] + +trait Mine {} + +// This one is fine +#[doc(tuple_variadic)] +impl Mine for (T,) {} + +trait Mine2 {} + +// This one is not +#[doc(tuple_variadic)] //~ ERROR +impl Mine for (T,U) {} + +fn main() {} diff --git a/src/test/rustdoc-ui/tuple-variadic-check.stderr b/src/test/rustdoc-ui/tuple-variadic-check.stderr new file mode 100644 index 0000000000000..030bc28a28736 --- /dev/null +++ b/src/test/rustdoc-ui/tuple-variadic-check.stderr @@ -0,0 +1,8 @@ +error: `#[doc(tuple_variadic)]` must used on the first of a set of tuple trait impls with varying arity + --> $DIR/tuple-variadic-check.rs:12:7 + | +LL | #[doc(tuple_variadic)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 94396711dd4a4c535664c0b85696bbe089198b8e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 13 Jun 2022 09:28:49 -0700 Subject: [PATCH 17/19] rustdoc: add missing article Co-authored-by: Jacob Hoffman-Andrews --- compiler/rustc_passes/src/check_attr.rs | 2 +- src/test/rustdoc-ui/tuple-variadic-check.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 93b2c14129ed7..1d94130f22204 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -815,7 +815,7 @@ impl CheckAttrVisitor<'_> { .sess .struct_span_err( meta.span(), - "`#[doc(tuple_variadic)]` must used on the first of a set of tuple trait impls with varying arity", + "`#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity", ) .emit(); return false; diff --git a/src/test/rustdoc-ui/tuple-variadic-check.stderr b/src/test/rustdoc-ui/tuple-variadic-check.stderr index 030bc28a28736..358d06d6a42dd 100644 --- a/src/test/rustdoc-ui/tuple-variadic-check.stderr +++ b/src/test/rustdoc-ui/tuple-variadic-check.stderr @@ -1,4 +1,4 @@ -error: `#[doc(tuple_variadic)]` must used on the first of a set of tuple trait impls with varying arity +error: `#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity --> $DIR/tuple-variadic-check.rs:12:7 | LL | #[doc(tuple_variadic)] From 2bbf44f655bc6b1073009cab56884b09666de6c3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 14 Jun 2022 12:21:38 -0700 Subject: [PATCH 18/19] rustdoc: change "variadic tuple" notation to look less like real syntax --- library/core/src/primitive_docs.rs | 8 ++++---- library/std/src/primitive_docs.rs | 8 ++++---- src/librustdoc/html/format.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index a19840ac57639..00793f7f9204d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -918,10 +918,10 @@ mod prim_str {} // linked to as `#trait-implementations-1` /// # Trait implementations /// -/// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. -/// When that is used, any trait bound expressed on `T` applies to each element of the tuple -/// independently. Note that this is a convenience notation to avoid repetitive documentation, -/// not valid Rust syntax. +/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying +/// length. When that is used, any trait bound expressed on `T` applies to each element of the +/// tuple independently. Note that this is a convenience notation to avoid repetitive +/// documentation, not valid Rust syntax. /// /// Due to a temporary restriction in Rust’s type system, the following traits are only /// implemented on tuples of arity 12 or less. In the future, this may change: diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index a19840ac57639..00793f7f9204d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -918,10 +918,10 @@ mod prim_str {} // linked to as `#trait-implementations-1` /// # Trait implementations /// -/// In this documentation the shorthand `(T, ...)` is used to represent tuples of varying length. -/// When that is used, any trait bound expressed on `T` applies to each element of the tuple -/// independently. Note that this is a convenience notation to avoid repetitive documentation, -/// not valid Rust syntax. +/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying +/// length. When that is used, any trait bound expressed on `T` applies to each element of the +/// tuple independently. Note that this is a convenience notation to avoid repetitive +/// documentation, not valid Rust syntax. /// /// Due to a temporary restriction in Rust’s type system, the following traits are only /// implemented on tuples of arity 12 or less. In the future, this may change: diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index c714549d0f545..5520430b04302 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1079,7 +1079,7 @@ impl clean::Impl { (self.kind.is_tuple_variadic() || self.kind.is_auto()) { // Hardcoded anchor library/core/src/primitive_docs.rs // Link should match `# Trait implementations` - primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}, ...)"), "#trait-implementations-1", cx)?; + primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?; } else if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { From f1d24beb6805e4d16d472964518c576421f8c009 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 14 Jun 2022 14:17:20 -0700 Subject: [PATCH 19/19] rustdoc: add test case for "variadic tuple" search notation --- src/test/rustdoc/primitive-tuple-variadic.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/rustdoc/primitive-tuple-variadic.rs diff --git a/src/test/rustdoc/primitive-tuple-variadic.rs b/src/test/rustdoc/primitive-tuple-variadic.rs new file mode 100644 index 0000000000000..4fd6254f6740d --- /dev/null +++ b/src/test/rustdoc/primitive-tuple-variadic.rs @@ -0,0 +1,18 @@ +// compile-flags: --crate-type lib --edition 2018 + +#![crate_name = "foo"] +#![feature(rustdoc_internals)] + +pub trait Foo {} + +// @has foo/trait.Foo.html +// @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl Foo for (T₁, T₂, …, Tₙ)' +#[doc(tuple_variadic)] +impl Foo for (T,) {} + +pub trait Bar {} + +// @has foo/trait.Bar.html +// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl Bar for (U₁, U₂, …, Uₙ)' +#[doc(tuple_variadic)] +impl Bar for (U,) {}