Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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_varadic) {
let msg = "`#[doc(tuple_varadic)]` 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 @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
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 @@ -1439,6 +1439,7 @@ symbols! {
tuple,
tuple_from_req,
tuple_indexing,
tuple_varadic,
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
39 changes: 28 additions & 11 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2313,23 +2313,40 @@ 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_varadic))]
#[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,)+) };
Expand Down
31 changes: 24 additions & 7 deletions library/core/src/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -883,18 +883,35 @@ 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_varadic))]
#[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,)+) };
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
69 changes: 51 additions & 18 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 @@ -895,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
///
Expand Down Expand Up @@ -949,6 +957,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_varadic))]
/// 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_varadic))]
/// 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