Skip to content

Commit 6ec3993

Browse files
committed
Auto merge of #97842 - notriddle:notriddle/tuple-docs, r=jsha,GuillaumeGomez
Improve the tuple and unit trait docs * Reduce duplicate impls; show only the `(T,)` and include a sentence saying that there exists ones up to twelve of them. * Show `Copy` and `Clone`. * Show auto traits like `Send` and `Sync`, and blanket impls like `Any`. Here's the new version: * <https://notriddle.com/notriddle-rustdoc-test/std/primitive.tuple.html> * <https://notriddle.com/notriddle-rustdoc-test/std/primitive.unit.html>
2 parents d40f24e + f1d24be commit 6ec3993

22 files changed

+468
-112
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+5
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
401401
let msg = "`#[doc(keyword)]` is meant for internal use only";
402402
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
403403
}
404+
405+
if nested_meta.has_name(sym::tuple_variadic) {
406+
let msg = "`#[doc(tuple_variadic)]` is meant for internal use only";
407+
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
408+
}
404409
}
405410
}
406411

compiler/rustc_passes/src/check_attr.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,37 @@ impl CheckAttrVisitor<'_> {
805805
true
806806
}
807807

808+
fn check_doc_tuple_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
809+
match self.tcx.hir().find(hir_id).and_then(|node| match node {
810+
hir::Node::Item(item) => Some(&item.kind),
811+
_ => None,
812+
}) {
813+
Some(ItemKind::Impl(ref i)) => {
814+
if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) {
815+
self.tcx
816+
.sess
817+
.struct_span_err(
818+
meta.span(),
819+
"`#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity",
820+
)
821+
.emit();
822+
return false;
823+
}
824+
}
825+
_ => {
826+
self.tcx
827+
.sess
828+
.struct_span_err(
829+
meta.span(),
830+
"`#[doc(keyword = \"...\")]` can only be used on impl blocks",
831+
)
832+
.emit();
833+
return false;
834+
}
835+
}
836+
true
837+
}
838+
808839
/// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. Returns `true` if valid.
809840
///
810841
/// A doc inlining attribute is invalid if it is applied to a non-`use` item, or
@@ -1065,6 +1096,13 @@ impl CheckAttrVisitor<'_> {
10651096
is_valid = false
10661097
}
10671098

1099+
sym::tuple_variadic
1100+
if !self.check_attr_not_crate_level(meta, hir_id, "tuple_variadic")
1101+
|| !self.check_doc_tuple_variadic(meta, hir_id) =>
1102+
{
1103+
is_valid = false
1104+
}
1105+
10681106
sym::html_favicon_url
10691107
| sym::html_logo_url
10701108
| sym::html_playground_url
@@ -1118,7 +1156,8 @@ impl CheckAttrVisitor<'_> {
11181156
| sym::no_inline
11191157
| sym::notable_trait
11201158
| sym::passes
1121-
| sym::plugins => {}
1159+
| sym::plugins
1160+
| sym::tuple_variadic => {}
11221161

11231162
sym::test => {
11241163
if !self.check_test_attr(meta, hir_id) {

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ symbols! {
14491449
tuple,
14501450
tuple_from_req,
14511451
tuple_indexing,
1452+
tuple_variadic,
14521453
two_phase,
14531454
ty,
14541455
type_alias_enum_variants,

library/core/src/clone.rs

-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ use crate::marker::Destruct;
9595
///
9696
/// * Function item types (i.e., the distinct types defined for each function)
9797
/// * Function pointer types (e.g., `fn() -> i32`)
98-
/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`)
9998
/// * Closure types, if they capture no value from the environment
10099
/// or if all such captured values implement `Clone` themselves.
101100
/// Note that variables captured by shared reference always implement `Clone`

library/core/src/fmt/mod.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -2313,29 +2313,46 @@ macro_rules! peel {
23132313
macro_rules! tuple {
23142314
() => ();
23152315
( $($name:ident,)+ ) => (
2316-
#[stable(feature = "rust1", since = "1.0.0")]
2317-
impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {
2318-
#[allow(non_snake_case, unused_assignments)]
2319-
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
2320-
let mut builder = f.debug_tuple("");
2321-
let ($(ref $name,)+) = *self;
2322-
$(
2323-
builder.field(&$name);
2324-
)+
2325-
2326-
builder.finish()
2316+
maybe_tuple_doc! {
2317+
$($name)+ @
2318+
#[stable(feature = "rust1", since = "1.0.0")]
2319+
impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {
2320+
#[allow(non_snake_case, unused_assignments)]
2321+
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
2322+
let mut builder = f.debug_tuple("");
2323+
let ($(ref $name,)+) = *self;
2324+
$(
2325+
builder.field(&$name);
2326+
)+
2327+
2328+
builder.finish()
2329+
}
23272330
}
23282331
}
23292332
peel! { $($name,)+ }
23302333
)
23312334
}
23322335

2336+
macro_rules! maybe_tuple_doc {
2337+
($a:ident @ #[$meta:meta] $item:item) => {
2338+
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
2339+
#[doc = "This trait is implemented for tuples up to twelve items long."]
2340+
#[$meta]
2341+
$item
2342+
};
2343+
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
2344+
#[doc(hidden)]
2345+
#[$meta]
2346+
$item
2347+
};
2348+
}
2349+
23332350
macro_rules! last_type {
23342351
($a:ident,) => { $a };
23352352
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
23362353
}
23372354

2338-
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2355+
tuple! { E, D, C, B, A, Z, Y, X, W, V, U, T, }
23392356

23402357
#[stable(feature = "rust1", since = "1.0.0")]
23412358
impl<T: Debug> Debug for [T] {

library/core/src/hash/mod.rs

+36-19
Original file line numberDiff line numberDiff line change
@@ -883,36 +883,53 @@ mod impls {
883883
);
884884

885885
( $($name:ident)+) => (
886-
#[stable(feature = "rust1", since = "1.0.0")]
887-
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
888-
#[allow(non_snake_case)]
889-
#[inline]
890-
fn hash<S: Hasher>(&self, state: &mut S) {
891-
let ($(ref $name,)+) = *self;
892-
$($name.hash(state);)+
886+
maybe_tuple_doc! {
887+
$($name)+ @
888+
#[stable(feature = "rust1", since = "1.0.0")]
889+
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
890+
#[allow(non_snake_case)]
891+
#[inline]
892+
fn hash<S: Hasher>(&self, state: &mut S) {
893+
let ($(ref $name,)+) = *self;
894+
$($name.hash(state);)+
895+
}
893896
}
894897
}
895898
);
896899
}
897900

901+
macro_rules! maybe_tuple_doc {
902+
($a:ident @ #[$meta:meta] $item:item) => {
903+
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
904+
#[doc = "This trait is implemented for tuples up to twelve items long."]
905+
#[$meta]
906+
$item
907+
};
908+
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
909+
#[doc(hidden)]
910+
#[$meta]
911+
$item
912+
};
913+
}
914+
898915
macro_rules! last_type {
899916
($a:ident,) => { $a };
900917
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
901918
}
902919

903920
impl_hash_tuple! {}
904-
impl_hash_tuple! { A }
905-
impl_hash_tuple! { A B }
906-
impl_hash_tuple! { A B C }
907-
impl_hash_tuple! { A B C D }
908-
impl_hash_tuple! { A B C D E }
909-
impl_hash_tuple! { A B C D E F }
910-
impl_hash_tuple! { A B C D E F G }
911-
impl_hash_tuple! { A B C D E F G H }
912-
impl_hash_tuple! { A B C D E F G H I }
913-
impl_hash_tuple! { A B C D E F G H I J }
914-
impl_hash_tuple! { A B C D E F G H I J K }
915-
impl_hash_tuple! { A B C D E F G H I J K L }
921+
impl_hash_tuple! { T }
922+
impl_hash_tuple! { T B }
923+
impl_hash_tuple! { T B C }
924+
impl_hash_tuple! { T B C D }
925+
impl_hash_tuple! { T B C D E }
926+
impl_hash_tuple! { T B C D E F }
927+
impl_hash_tuple! { T B C D E F G }
928+
impl_hash_tuple! { T B C D E F G H }
929+
impl_hash_tuple! { T B C D E F G H I }
930+
impl_hash_tuple! { T B C D E F G H I J }
931+
impl_hash_tuple! { T B C D E F G H I J K }
932+
impl_hash_tuple! { T B C D E F G H I J K L }
916933

917934
#[stable(feature = "rust1", since = "1.0.0")]
918935
impl<T: Hash> Hash for [T] {

library/core/src/marker.rs

-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,6 @@ pub trait StructuralEq {
359359
///
360360
/// * Function item types (i.e., the distinct types defined for each function)
361361
/// * Function pointer types (e.g., `fn() -> i32`)
362-
/// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`)
363362
/// * Closure types, if they capture no value from the environment
364363
/// or if all such captured values implement `Copy` themselves.
365364
/// Note that variables captured by shared reference always implement `Copy`

library/core/src/primitive_docs.rs

+70-6
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,27 @@ mod prim_char {}
439439
#[stable(feature = "rust1", since = "1.0.0")]
440440
mod prim_unit {}
441441

442+
// Required to make auto trait impls render.
443+
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
444+
#[doc(hidden)]
445+
impl () {}
446+
447+
// Fake impl that's only really used for docs.
448+
#[cfg(doc)]
449+
#[stable(feature = "rust1", since = "1.0.0")]
450+
impl Clone for () {
451+
fn clone(&self) -> Self {
452+
loop {}
453+
}
454+
}
455+
456+
// Fake impl that's only really used for docs.
457+
#[cfg(doc)]
458+
#[stable(feature = "rust1", since = "1.0.0")]
459+
impl Copy for () {
460+
// empty
461+
}
462+
442463
#[doc(primitive = "pointer")]
443464
#[doc(alias = "ptr")]
444465
#[doc(alias = "*")]
@@ -893,13 +914,18 @@ mod prim_str {}
893914
///
894915
/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
895916
///
917+
// Hardcoded anchor in src/librustdoc/html/format.rs
918+
// linked to as `#trait-implementations-1`
896919
/// # Trait implementations
897920
///
898-
/// If every type inside a tuple implements one of the following traits, then a
899-
/// tuple itself also implements it.
921+
/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying
922+
/// length. When that is used, any trait bound expressed on `T` applies to each element of the
923+
/// tuple independently. Note that this is a convenience notation to avoid repetitive
924+
/// documentation, not valid Rust syntax.
925+
///
926+
/// Due to a temporary restriction in Rust’s type system, the following traits are only
927+
/// implemented on tuples of arity 12 or less. In the future, this may change:
900928
///
901-
/// * [`Clone`]
902-
/// * [`Copy`]
903929
/// * [`PartialEq`]
904930
/// * [`Eq`]
905931
/// * [`PartialOrd`]
@@ -911,8 +937,21 @@ mod prim_str {}
911937
/// [`Debug`]: fmt::Debug
912938
/// [`Hash`]: hash::Hash
913939
///
914-
/// Due to a temporary restriction in Rust's type system, these traits are only
915-
/// implemented on tuples of arity 12 or less. In the future, this may change.
940+
/// The following traits are implemented for tuples of any length. These traits have
941+
/// implementations that are automatically generated by the compiler, so are not limited by
942+
/// missing language features.
943+
///
944+
/// * [`Clone`]
945+
/// * [`Copy`]
946+
/// * [`Send`]
947+
/// * [`Sync`]
948+
/// * [`Unpin`]
949+
/// * [`UnwindSafe`]
950+
/// * [`RefUnwindSafe`]
951+
///
952+
/// [`Unpin`]: marker::Unpin
953+
/// [`UnwindSafe`]: panic::UnwindSafe
954+
/// [`RefUnwindSafe`]: panic::RefUnwindSafe
916955
///
917956
/// # Examples
918957
///
@@ -949,6 +988,31 @@ mod prim_str {}
949988
#[stable(feature = "rust1", since = "1.0.0")]
950989
mod prim_tuple {}
951990

991+
// Required to make auto trait impls render.
992+
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
993+
#[doc(hidden)]
994+
impl<T> (T,) {}
995+
996+
// Fake impl that's only really used for docs.
997+
#[cfg(doc)]
998+
#[stable(feature = "rust1", since = "1.0.0")]
999+
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
1000+
/// This trait is implemented on arbitrary-length tuples.
1001+
impl<T: Clone> Clone for (T,) {
1002+
fn clone(&self) -> Self {
1003+
loop {}
1004+
}
1005+
}
1006+
1007+
// Fake impl that's only really used for docs.
1008+
#[cfg(doc)]
1009+
#[stable(feature = "rust1", since = "1.0.0")]
1010+
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
1011+
/// This trait is implemented on arbitrary-length tuples.
1012+
impl<T: Copy> Copy for (T,) {
1013+
// empty
1014+
}
1015+
9521016
#[doc(primitive = "f32")]
9531017
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
9541018
///

0 commit comments

Comments
 (0)