Skip to content

Commit

Permalink
Auto merge of #97842 - notriddle:notriddle/tuple-docs, r=jsha,Guillau…
Browse files Browse the repository at this point in the history
…meGomez

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>
  • Loading branch information
bors committed Jun 16, 2022
2 parents d40f24e + f1d24be commit 6ec3993
Show file tree
Hide file tree
Showing 22 changed files with 468 additions and 112 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_variadic) {
let msg = "`#[doc(tuple_variadic)]` is meant for internal use only";
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
}
}
}

Expand Down
41 changes: 40 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,37 @@ impl CheckAttrVisitor<'_> {
true
}

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,
}) {
Some(ItemKind::Impl(ref i)) => {
if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) {
self.tcx
.sess
.struct_span_err(
meta.span(),
"`#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity",
)
.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
Expand Down Expand Up @@ -1065,6 +1096,13 @@ impl CheckAttrVisitor<'_> {
is_valid = false
}

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
}

sym::html_favicon_url
| sym::html_logo_url
| sym::html_playground_url
Expand Down Expand Up @@ -1118,7 +1156,8 @@ impl CheckAttrVisitor<'_> {
| sym::no_inline
| sym::notable_trait
| sym::passes
| sym::plugins => {}
| sym::plugins
| sym::tuple_variadic => {}

sym::test => {
if !self.check_test_attr(meta, hir_id) {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,7 @@ symbols! {
tuple,
tuple_from_req,
tuple_indexing,
tuple_variadic,
two_phase,
ty,
type_alias_enum_variants,
Expand Down
1 change: 0 additions & 1 deletion library/core/src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
41 changes: 29 additions & 12 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2313,29 +2313,46 @@ 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) => {
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
#[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,)+) };
}

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<T: Debug> Debug for [T] {
Expand Down
55 changes: 36 additions & 19 deletions library/core/src/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -883,36 +883,53 @@ 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<S: Hasher>(&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<S: Hasher>(&self, state: &mut S) {
let ($(ref $name,)+) = *self;
$($name.hash(state);)+
}
}
}
);
}

macro_rules! maybe_tuple_doc {
($a:ident @ #[$meta:meta] $item:item) => {
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
#[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,)+) };
}

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<T: Hash> Hash for [T] {
Expand Down
1 change: 0 additions & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
76 changes: 70 additions & 6 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,27 @@ 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 () {}

// 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 = "*")]
Expand Down Expand Up @@ -893,13 +914,18 @@ 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
///
/// If every type inside a tuple implements one of the following traits, then a
/// tuple itself also implements it.
/// 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:
///
/// * [`Clone`]
/// * [`Copy`]
/// * [`PartialEq`]
/// * [`Eq`]
/// * [`PartialOrd`]
Expand All @@ -911,8 +937,21 @@ mod prim_str {}
/// [`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.
/// 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
///
Expand Down Expand Up @@ -949,6 +988,31 @@ 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> (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_variadic))]
/// This trait is implemented on arbitrary-length tuples.
impl<T: Clone> 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")]
#[cfg_attr(not(bootstrap), doc(tuple_variadic))]
/// This trait is implemented on arbitrary-length tuples.
impl<T: Copy> Copy for (T,) {
// empty
}

#[doc(primitive = "f32")]
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
///
Expand Down
Loading

0 comments on commit 6ec3993

Please sign in to comment.