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>
This commit is contained in:
commit
6ec3993ef4
22 changed files with 467 additions and 111 deletions
|
@ -401,6 +401,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
let msg = "`#[doc(keyword)]` is meant for internal use only";
|
let msg = "`#[doc(keyword)]` is meant for internal use only";
|
||||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -805,6 +805,37 @@ impl CheckAttrVisitor<'_> {
|
||||||
true
|
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.
|
/// 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
|
/// A doc inlining attribute is invalid if it is applied to a non-`use` item, or
|
||||||
|
@ -1065,6 +1096,13 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid = false
|
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_favicon_url
|
||||||
| sym::html_logo_url
|
| sym::html_logo_url
|
||||||
| sym::html_playground_url
|
| sym::html_playground_url
|
||||||
|
@ -1118,7 +1156,8 @@ impl CheckAttrVisitor<'_> {
|
||||||
| sym::no_inline
|
| sym::no_inline
|
||||||
| sym::notable_trait
|
| sym::notable_trait
|
||||||
| sym::passes
|
| sym::passes
|
||||||
| sym::plugins => {}
|
| sym::plugins
|
||||||
|
| sym::tuple_variadic => {}
|
||||||
|
|
||||||
sym::test => {
|
sym::test => {
|
||||||
if !self.check_test_attr(meta, hir_id) {
|
if !self.check_test_attr(meta, hir_id) {
|
||||||
|
|
|
@ -1449,6 +1449,7 @@ symbols! {
|
||||||
tuple,
|
tuple,
|
||||||
tuple_from_req,
|
tuple_from_req,
|
||||||
tuple_indexing,
|
tuple_indexing,
|
||||||
|
tuple_variadic,
|
||||||
two_phase,
|
two_phase,
|
||||||
ty,
|
ty,
|
||||||
type_alias_enum_variants,
|
type_alias_enum_variants,
|
||||||
|
|
|
@ -95,7 +95,6 @@ use crate::marker::Destruct;
|
||||||
///
|
///
|
||||||
/// * Function item types (i.e., the distinct types defined for each function)
|
/// * Function item types (i.e., the distinct types defined for each function)
|
||||||
/// * Function pointer types (e.g., `fn() -> i32`)
|
/// * 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
|
/// * Closure types, if they capture no value from the environment
|
||||||
/// or if all such captured values implement `Clone` themselves.
|
/// or if all such captured values implement `Clone` themselves.
|
||||||
/// Note that variables captured by shared reference always implement `Clone`
|
/// Note that variables captured by shared reference always implement `Clone`
|
||||||
|
|
|
@ -2313,29 +2313,46 @@ macro_rules! peel {
|
||||||
macro_rules! tuple {
|
macro_rules! tuple {
|
||||||
() => ();
|
() => ();
|
||||||
( $($name:ident,)+ ) => (
|
( $($name:ident,)+ ) => (
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
maybe_tuple_doc! {
|
||||||
impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {
|
$($name)+ @
|
||||||
#[allow(non_snake_case, unused_assignments)]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {
|
||||||
let mut builder = f.debug_tuple("");
|
#[allow(non_snake_case, unused_assignments)]
|
||||||
let ($(ref $name,)+) = *self;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
$(
|
let mut builder = f.debug_tuple("");
|
||||||
builder.field(&$name);
|
let ($(ref $name,)+) = *self;
|
||||||
)+
|
$(
|
||||||
|
builder.field(&$name);
|
||||||
|
)+
|
||||||
|
|
||||||
builder.finish()
|
builder.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
peel! { $($name,)+ }
|
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 {
|
macro_rules! last_type {
|
||||||
($a:ident,) => { $a };
|
($a:ident,) => { $a };
|
||||||
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Debug> Debug for [T] {
|
impl<T: Debug> Debug for [T] {
|
||||||
|
|
|
@ -883,36 +883,53 @@ mod impls {
|
||||||
);
|
);
|
||||||
|
|
||||||
( $($name:ident)+) => (
|
( $($name:ident)+) => (
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
maybe_tuple_doc! {
|
||||||
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
|
$($name)+ @
|
||||||
#[allow(non_snake_case)]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
|
||||||
fn hash<S: Hasher>(&self, state: &mut S) {
|
#[allow(non_snake_case)]
|
||||||
let ($(ref $name,)+) = *self;
|
#[inline]
|
||||||
$($name.hash(state);)+
|
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 {
|
macro_rules! last_type {
|
||||||
($a:ident,) => { $a };
|
($a:ident,) => { $a };
|
||||||
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
|
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_hash_tuple! {}
|
impl_hash_tuple! {}
|
||||||
impl_hash_tuple! { A }
|
impl_hash_tuple! { T }
|
||||||
impl_hash_tuple! { A B }
|
impl_hash_tuple! { T B }
|
||||||
impl_hash_tuple! { A B C }
|
impl_hash_tuple! { T B C }
|
||||||
impl_hash_tuple! { A B C D }
|
impl_hash_tuple! { T B C D }
|
||||||
impl_hash_tuple! { A B C D E }
|
impl_hash_tuple! { T B C D E }
|
||||||
impl_hash_tuple! { A B C D E F }
|
impl_hash_tuple! { T B C D E F }
|
||||||
impl_hash_tuple! { A B C D E F G }
|
impl_hash_tuple! { T B C D E F G }
|
||||||
impl_hash_tuple! { A B C D E F G H }
|
impl_hash_tuple! { T B C D E F G H }
|
||||||
impl_hash_tuple! { A B C D E F G H I }
|
impl_hash_tuple! { T B C D E F G H I }
|
||||||
impl_hash_tuple! { A B C D E F G H I J }
|
impl_hash_tuple! { T 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! { T 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 B C D E F G H I J K L }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Hash> Hash for [T] {
|
impl<T: Hash> Hash for [T] {
|
||||||
|
|
|
@ -359,7 +359,6 @@ pub trait StructuralEq {
|
||||||
///
|
///
|
||||||
/// * Function item types (i.e., the distinct types defined for each function)
|
/// * Function item types (i.e., the distinct types defined for each function)
|
||||||
/// * Function pointer types (e.g., `fn() -> i32`)
|
/// * 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
|
/// * Closure types, if they capture no value from the environment
|
||||||
/// or if all such captured values implement `Copy` themselves.
|
/// or if all such captured values implement `Copy` themselves.
|
||||||
/// Note that variables captured by shared reference always implement `Copy`
|
/// Note that variables captured by shared reference always implement `Copy`
|
||||||
|
|
|
@ -439,6 +439,27 @@ mod prim_char {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_unit {}
|
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(primitive = "pointer")]
|
||||||
#[doc(alias = "ptr")]
|
#[doc(alias = "ptr")]
|
||||||
#[doc(alias = "*")]
|
#[doc(alias = "*")]
|
||||||
|
@ -893,13 +914,18 @@ mod prim_str {}
|
||||||
///
|
///
|
||||||
/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
|
/// 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
|
/// # Trait implementations
|
||||||
///
|
///
|
||||||
/// If every type inside a tuple implements one of the following traits, then a
|
/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying
|
||||||
/// tuple itself also implements it.
|
/// 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`]
|
/// * [`PartialEq`]
|
||||||
/// * [`Eq`]
|
/// * [`Eq`]
|
||||||
/// * [`PartialOrd`]
|
/// * [`PartialOrd`]
|
||||||
|
@ -911,8 +937,21 @@ mod prim_str {}
|
||||||
/// [`Debug`]: fmt::Debug
|
/// [`Debug`]: fmt::Debug
|
||||||
/// [`Hash`]: hash::Hash
|
/// [`Hash`]: hash::Hash
|
||||||
///
|
///
|
||||||
/// Due to a temporary restriction in Rust's type system, these traits are only
|
/// The following traits are implemented for tuples of any length. These traits have
|
||||||
/// implemented on tuples of arity 12 or less. In the future, this may change.
|
/// 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
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -949,6 +988,31 @@ mod prim_str {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_tuple {}
|
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")]
|
#[doc(primitive = "f32")]
|
||||||
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
|
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
|
||||||
///
|
///
|
||||||
|
|
|
@ -19,75 +19,106 @@ macro_rules! tuple_impls {
|
||||||
};
|
};
|
||||||
// "Private" internal implementation
|
// "Private" internal implementation
|
||||||
(@impl $( $T:ident )+) => {
|
(@impl $( $T:ident )+) => {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
maybe_tuple_doc! {
|
||||||
impl<$($T:PartialEq),+> PartialEq for ($($T,)+)
|
$($T)+ @
|
||||||
where
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
last_type!($($T,)+): ?Sized
|
impl<$($T:PartialEq),+> PartialEq for ($($T,)+)
|
||||||
{
|
where
|
||||||
#[inline]
|
last_type!($($T,)+): ?Sized
|
||||||
fn eq(&self, other: &($($T,)+)) -> bool {
|
{
|
||||||
$( ${ignore(T)} self.${index()} == other.${index()} )&&+
|
#[inline]
|
||||||
}
|
fn eq(&self, other: &($($T,)+)) -> bool {
|
||||||
#[inline]
|
$( ${ignore(T)} self.${index()} == other.${index()} )&&+
|
||||||
fn ne(&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")]
|
maybe_tuple_doc! {
|
||||||
impl<$($T:Eq),+> Eq for ($($T,)+)
|
$($T)+ @
|
||||||
where
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
last_type!($($T,)+): ?Sized
|
impl<$($T:Eq),+> Eq for ($($T,)+)
|
||||||
{}
|
where
|
||||||
|
last_type!($($T,)+): ?Sized
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
maybe_tuple_doc! {
|
||||||
impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
|
$($T)+ @
|
||||||
where
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
last_type!($($T,)+): ?Sized
|
impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
|
||||||
{
|
where
|
||||||
#[inline]
|
last_type!($($T,)+): ?Sized
|
||||||
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
{
|
||||||
lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
#[inline]
|
||||||
}
|
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
||||||
#[inline]
|
lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
||||||
fn lt(&self, other: &($($T,)+)) -> bool {
|
}
|
||||||
lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
#[inline]
|
||||||
}
|
fn lt(&self, other: &($($T,)+)) -> bool {
|
||||||
#[inline]
|
lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
||||||
fn le(&self, other: &($($T,)+)) -> bool {
|
}
|
||||||
lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
#[inline]
|
||||||
}
|
fn le(&self, other: &($($T,)+)) -> bool {
|
||||||
#[inline]
|
lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
||||||
fn ge(&self, other: &($($T,)+)) -> bool {
|
}
|
||||||
lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
#[inline]
|
||||||
}
|
fn ge(&self, other: &($($T,)+)) -> bool {
|
||||||
#[inline]
|
lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
||||||
fn gt(&self, other: &($($T,)+)) -> bool {
|
}
|
||||||
lexical_ord!(gt, $( ${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")]
|
maybe_tuple_doc! {
|
||||||
impl<$($T:Ord),+> Ord for ($($T,)+)
|
$($T)+ @
|
||||||
where
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
last_type!($($T,)+): ?Sized
|
impl<$($T:Ord),+> Ord for ($($T,)+)
|
||||||
{
|
where
|
||||||
#[inline]
|
last_type!($($T,)+): ?Sized
|
||||||
fn cmp(&self, other: &($($T,)+)) -> Ordering {
|
{
|
||||||
lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
#[inline]
|
||||||
|
fn cmp(&self, other: &($($T,)+)) -> Ordering {
|
||||||
|
lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
maybe_tuple_doc! {
|
||||||
impl<$($T:Default),+> Default for ($($T,)+) {
|
$($T)+ @
|
||||||
#[inline]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn default() -> ($($T,)+) {
|
impl<$($T:Default),+> Default for ($($T,)+) {
|
||||||
($({ let x: $T = Default::default(); x},)+)
|
#[inline]
|
||||||
|
fn default() -> ($($T,)+) {
|
||||||
|
($({ let x: $T = Default::default(); x},)+)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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))]
|
||||||
|
#[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.
|
// Constructs an expression that performs a lexical ordering using method $rel.
|
||||||
// The values are interleaved, so the macro invocation for
|
// The values are interleaved, so the macro invocation for
|
||||||
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
|
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
|
||||||
|
@ -125,4 +156,4 @@ macro_rules! last_type {
|
||||||
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
|
($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);
|
||||||
|
|
|
@ -439,6 +439,27 @@ mod prim_char {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_unit {}
|
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(primitive = "pointer")]
|
||||||
#[doc(alias = "ptr")]
|
#[doc(alias = "ptr")]
|
||||||
#[doc(alias = "*")]
|
#[doc(alias = "*")]
|
||||||
|
@ -893,13 +914,18 @@ mod prim_str {}
|
||||||
///
|
///
|
||||||
/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
|
/// 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
|
/// # Trait implementations
|
||||||
///
|
///
|
||||||
/// If every type inside a tuple implements one of the following traits, then a
|
/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying
|
||||||
/// tuple itself also implements it.
|
/// 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`]
|
/// * [`PartialEq`]
|
||||||
/// * [`Eq`]
|
/// * [`Eq`]
|
||||||
/// * [`PartialOrd`]
|
/// * [`PartialOrd`]
|
||||||
|
@ -911,8 +937,21 @@ mod prim_str {}
|
||||||
/// [`Debug`]: fmt::Debug
|
/// [`Debug`]: fmt::Debug
|
||||||
/// [`Hash`]: hash::Hash
|
/// [`Hash`]: hash::Hash
|
||||||
///
|
///
|
||||||
/// Due to a temporary restriction in Rust's type system, these traits are only
|
/// The following traits are implemented for tuples of any length. These traits have
|
||||||
/// implemented on tuples of arity 12 or less. In the future, this may change.
|
/// 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
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -949,6 +988,31 @@ mod prim_str {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_tuple {}
|
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")]
|
#[doc(primitive = "f32")]
|
||||||
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
|
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
|
||||||
///
|
///
|
||||||
|
|
|
@ -500,7 +500,11 @@ pub(crate) fn build_impl(
|
||||||
for_,
|
for_,
|
||||||
items: trait_items,
|
items: trait_items,
|
||||||
polarity,
|
polarity,
|
||||||
kind: ImplKind::Normal,
|
kind: if utils::has_doc_flag(tcx, did, sym::tuple_variadic) {
|
||||||
|
ImplKind::TupleVaradic
|
||||||
|
} else {
|
||||||
|
ImplKind::Normal
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
box merged_attrs,
|
box merged_attrs,
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -1999,7 +1999,11 @@ fn clean_impl<'tcx>(
|
||||||
for_,
|
for_,
|
||||||
items,
|
items,
|
||||||
polarity: tcx.impl_polarity(def_id),
|
polarity: tcx.impl_polarity(def_id),
|
||||||
kind: ImplKind::Normal,
|
kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_variadic) {
|
||||||
|
ImplKind::TupleVaradic
|
||||||
|
} else {
|
||||||
|
ImplKind::Normal
|
||||||
|
},
|
||||||
});
|
});
|
||||||
Item::from_hir_id_and_parts(hir_id, None, kind, cx)
|
Item::from_hir_id_and_parts(hir_id, None, kind, cx)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1750,7 +1750,7 @@ pub(crate) enum PrimitiveType {
|
||||||
Never,
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 2>>;
|
type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
|
||||||
impl PrimitiveType {
|
impl PrimitiveType {
|
||||||
pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
|
pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
|
||||||
use ast::{FloatTy, IntTy, UintTy};
|
use ast::{FloatTy, IntTy, UintTy};
|
||||||
|
@ -1839,10 +1839,10 @@ impl PrimitiveType {
|
||||||
//
|
//
|
||||||
// Either manually update this arrayvec at this point
|
// Either manually update this arrayvec at this point
|
||||||
// or start with a more complex refactoring.
|
// 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)),
|
Unit => single(TupleSimplifiedType(0)),
|
||||||
RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into(),
|
RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
|
||||||
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into(),
|
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
|
||||||
// FIXME: This will be wrong if we ever add inherent impls
|
// FIXME: This will be wrong if we ever add inherent impls
|
||||||
// for function pointers.
|
// for function pointers.
|
||||||
Fn => ArrayVec::new(),
|
Fn => ArrayVec::new(),
|
||||||
|
@ -2394,6 +2394,7 @@ impl Impl {
|
||||||
pub(crate) enum ImplKind {
|
pub(crate) enum ImplKind {
|
||||||
Normal,
|
Normal,
|
||||||
Auto,
|
Auto,
|
||||||
|
TupleVaradic,
|
||||||
Blanket(Box<Type>),
|
Blanket(Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2406,6 +2407,10 @@ impl ImplKind {
|
||||||
matches!(self, ImplKind::Blanket(_))
|
matches!(self, ImplKind::Blanket(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_tuple_variadic(&self) -> bool {
|
||||||
|
matches!(self, ImplKind::TupleVaradic)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
|
pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
|
||||||
match self {
|
match self {
|
||||||
ImplKind::Blanket(ty) => Some(ty),
|
ImplKind::Blanket(ty) => Some(ty),
|
||||||
|
|
|
@ -713,6 +713,16 @@ fn primitive_link(
|
||||||
prim: clean::PrimitiveType,
|
prim: clean::PrimitiveType,
|
||||||
name: &str,
|
name: &str,
|
||||||
cx: &Context<'_>,
|
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 {
|
) -> fmt::Result {
|
||||||
let m = &cx.cache();
|
let m = &cx.cache();
|
||||||
let mut needs_termination = false;
|
let mut needs_termination = false;
|
||||||
|
@ -723,7 +733,7 @@ fn primitive_link(
|
||||||
let len = if len == 0 { 0 } else { len - 1 };
|
let len = if len == 0 { 0 } else { len - 1 };
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"<a class=\"primitive\" href=\"{}primitive.{}.html\">",
|
"<a class=\"primitive\" href=\"{}primitive.{}.html{fragment}\">",
|
||||||
"../".repeat(len),
|
"../".repeat(len),
|
||||||
prim.as_sym()
|
prim.as_sym()
|
||||||
)?;
|
)?;
|
||||||
|
@ -754,7 +764,7 @@ fn primitive_link(
|
||||||
};
|
};
|
||||||
if let Some(mut loc) = loc {
|
if let Some(mut loc) = loc {
|
||||||
loc.push_fmt(format_args!("primitive.{}.html", prim.as_sym()));
|
loc.push_fmt(format_args!("primitive.{}.html", prim.as_sym()));
|
||||||
write!(f, "<a class=\"primitive\" href=\"{}\">", loc.finish())?;
|
write!(f, "<a class=\"primitive\" href=\"{}{fragment}\">", loc.finish())?;
|
||||||
needs_termination = true;
|
needs_termination = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1039,7 +1049,13 @@ impl clean::Impl {
|
||||||
write!(f, " for ")?;
|
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_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}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?;
|
||||||
|
} else if let Some(ty) = self.kind.as_blanket_ty() {
|
||||||
fmt_type(ty, f, use_absolute, cx)?;
|
fmt_type(ty, f, use_absolute, cx)?;
|
||||||
} else {
|
} else {
|
||||||
fmt_type(&self.for_, f, use_absolute, cx)?;
|
fmt_type(&self.for_, f, use_absolute, cx)?;
|
||||||
|
|
|
@ -552,7 +552,7 @@ impl FromWithTcx<clean::Impl> for Impl {
|
||||||
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
||||||
// FIXME: use something like ImplKind in JSON?
|
// FIXME: use something like ImplKind in JSON?
|
||||||
let (synthetic, blanket_impl) = match kind {
|
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::Auto => (true, None),
|
||||||
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
|
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
|
||||||
};
|
};
|
||||||
|
|
15
src/test/rustdoc-ui/tuple-variadic-check.rs
Normal file
15
src/test/rustdoc-ui/tuple-variadic-check.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#![feature(rustdoc_internals)]
|
||||||
|
|
||||||
|
trait Mine {}
|
||||||
|
|
||||||
|
// This one is fine
|
||||||
|
#[doc(tuple_variadic)]
|
||||||
|
impl<T> Mine for (T,) {}
|
||||||
|
|
||||||
|
trait Mine2 {}
|
||||||
|
|
||||||
|
// This one is not
|
||||||
|
#[doc(tuple_variadic)] //~ ERROR
|
||||||
|
impl<T, U> Mine for (T,U) {}
|
||||||
|
|
||||||
|
fn main() {}
|
8
src/test/rustdoc-ui/tuple-variadic-check.stderr
Normal file
8
src/test/rustdoc-ui/tuple-variadic-check.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
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)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
22
src/test/rustdoc/primitive-tuple-auto-trait.rs
Normal file
22
src/test/rustdoc/primitive-tuple-auto-trait.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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!
|
||||||
|
///
|
||||||
|
// 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 {}
|
18
src/test/rustdoc/primitive-tuple-variadic.rs
Normal file
18
src/test/rustdoc/primitive-tuple-variadic.rs
Normal file
|
@ -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<T> Foo for (T₁, T₂, …, Tₙ)'
|
||||||
|
#[doc(tuple_variadic)]
|
||||||
|
impl<T> Foo for (T,) {}
|
||||||
|
|
||||||
|
pub trait Bar {}
|
||||||
|
|
||||||
|
// @has foo/trait.Bar.html
|
||||||
|
// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
|
||||||
|
#[doc(tuple_variadic)]
|
||||||
|
impl<U: Foo> Bar for (U,) {}
|
14
src/test/rustdoc/primitive-unit-auto-trait.rs
Normal file
14
src/test/rustdoc/primitive-unit-auto-trait.rs
Normal file
|
@ -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 {}
|
|
@ -2,4 +2,9 @@
|
||||||
/// wonderful
|
/// wonderful
|
||||||
mod foo {}
|
mod foo {}
|
||||||
|
|
||||||
|
trait Mine {}
|
||||||
|
|
||||||
|
#[doc(tuple_variadic)] //~ ERROR: `#[doc(tuple_variadic)]` is meant for internal use only
|
||||||
|
impl<T> Mine for (T,) {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -7,6 +7,15 @@ LL | #[doc(keyword = "match")]
|
||||||
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
||||||
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
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 <https://github.com/rust-lang/rust/issues/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`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue