[`RFC 3086`] Attempt to try to resolve blocking concerns Implements what is described at https://github.com/rust-lang/rust/issues/83527#issuecomment-1744822345 to hopefully make some progress. It is unknown if such approach is or isn't desired due to the lack of further feedback, as such, it is probably best to nominate this PR to the official entities. `@rustbot` labels +I-compiler-nominated
360 lines
12 KiB
Rust
360 lines
12 KiB
Rust
// See core/src/primitive_docs.rs for documentation.
|
|
|
|
use crate::cmp::Ordering::{self, *};
|
|
use crate::marker::ConstParamTy;
|
|
use crate::marker::{StructuralEq, StructuralPartialEq};
|
|
|
|
// Recursive macro for implementing n-ary tuple functions and operations
|
|
//
|
|
// Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C)
|
|
// will implement everything for (A, B, C), (A, B) and (A,).
|
|
#[cfg(bootstrap)]
|
|
macro_rules! tuple_impls {
|
|
// Stopping criteria (1-ary tuple)
|
|
($T:ident) => {
|
|
tuple_impls!(@impl $T);
|
|
};
|
|
// Running criteria (n-ary tuple, with n >= 2)
|
|
($T:ident $( $U:ident )+) => {
|
|
tuple_impls!($( $U )+);
|
|
tuple_impls!(@impl $T $( $U )+);
|
|
};
|
|
// "Private" internal implementation
|
|
(@impl $( $T:ident )+) => {
|
|
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()} )||+
|
|
}
|
|
}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<$($T: Eq),+> Eq for ($($T,)+)
|
|
where
|
|
last_type!($($T,)+): ?Sized
|
|
{}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+) {}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T),+> StructuralPartialEq for ($($T,)+) {}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T),+> StructuralEq for ($($T,)+) {}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+)
|
|
where
|
|
last_type!($($T,)+): ?Sized
|
|
{
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
|
lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn lt(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(lt, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn le(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(le, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn ge(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(ge, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn gt(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(gt, Greater, $( ${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()} ),+)
|
|
}
|
|
}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<$($T: Default),+> Default for ($($T,)+) {
|
|
#[inline]
|
|
fn default() -> ($($T,)+) {
|
|
($($T::default(),)+)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
|
impl<T> From<[T; ${count(T)}]> for ($(${ignore(T)} T,)+) {
|
|
#[inline]
|
|
#[allow(non_snake_case)]
|
|
fn from(array: [T; ${count(T)}]) -> Self {
|
|
let [$($T,)+] = array;
|
|
($($T,)+)
|
|
}
|
|
}
|
|
|
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
|
impl<T> From<($(${ignore(T)} T,)+)> for [T; ${count(T)}] {
|
|
#[inline]
|
|
#[allow(non_snake_case)]
|
|
fn from(tuple: ($(${ignore(T)} T,)+)) -> Self {
|
|
let ($($T,)+) = tuple;
|
|
[$($T,)+]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recursive macro for implementing n-ary tuple functions and operations
|
|
//
|
|
// Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C)
|
|
// will implement everything for (A, B, C), (A, B) and (A,).
|
|
#[cfg(not(bootstrap))]
|
|
macro_rules! tuple_impls {
|
|
// Stopping criteria (1-ary tuple)
|
|
($T:ident) => {
|
|
tuple_impls!(@impl $T);
|
|
};
|
|
// Running criteria (n-ary tuple, with n >= 2)
|
|
($T:ident $( $U:ident )+) => {
|
|
tuple_impls!($( $U )+);
|
|
tuple_impls!(@impl $T $( $U )+);
|
|
};
|
|
// "Private" internal implementation
|
|
(@impl $( $T:ident )+) => {
|
|
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()} )||+
|
|
}
|
|
}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<$($T: Eq),+> Eq for ($($T,)+)
|
|
where
|
|
last_type!($($T,)+): ?Sized
|
|
{}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+)
|
|
{}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T),+> StructuralPartialEq for ($($T,)+)
|
|
{}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[unstable(feature = "structural_match", issue = "31434")]
|
|
impl<$($T),+> StructuralEq for ($($T,)+)
|
|
{}
|
|
}
|
|
|
|
maybe_tuple_doc! {
|
|
$($T)+ @
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+)
|
|
where
|
|
last_type!($($T,)+): ?Sized
|
|
{
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
|
lexical_partial_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn lt(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn le(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn ge(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
|
}
|
|
#[inline]
|
|
fn gt(&self, other: &($($T,)+)) -> bool {
|
|
lexical_ord!(gt, Greater, $( ${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()} ),+)
|
|
}
|
|
}
|
|
}
|
|
|
|
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},)+)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
|
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
|
|
#[inline]
|
|
#[allow(non_snake_case)]
|
|
fn from(array: [T; ${count($T)}]) -> Self {
|
|
let [$($T,)+] = array;
|
|
($($T,)+)
|
|
}
|
|
}
|
|
|
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
|
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
|
|
#[inline]
|
|
#[allow(non_snake_case)]
|
|
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
|
|
let ($($T,)+) = tuple;
|
|
[$($T,)+]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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) => {
|
|
#[doc(fake_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
|
|
};
|
|
}
|
|
|
|
#[inline]
|
|
const fn ordering_is_some(c: Option<Ordering>, x: Ordering) -> bool {
|
|
// FIXME: Just use `==` once that's const-stable on `Option`s.
|
|
// This is mapping `None` to 2 and then doing the comparison afterwards
|
|
// because it optimizes better (`None::<Ordering>` is represented as 2).
|
|
x as i8
|
|
== match c {
|
|
Some(c) => c as i8,
|
|
None => 2,
|
|
}
|
|
}
|
|
|
|
// 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, opt_is_lt, a1, b1,
|
|
// a2, b2, a3, b3)` (and similarly for `lexical_cmp`)
|
|
//
|
|
// `$ne_rel` is only used to determine the result after checking that they're
|
|
// not equal, so `lt` and `le` can both just use `Less`.
|
|
macro_rules! lexical_ord {
|
|
($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
|
|
let c = PartialOrd::partial_cmp(&$a, &$b);
|
|
if !ordering_is_some(c, Equal) { ordering_is_some(c, $ne_rel) }
|
|
else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) }
|
|
}};
|
|
($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => {
|
|
// Use the specific method for the last element
|
|
PartialOrd::$rel(&$a, &$b)
|
|
};
|
|
}
|
|
|
|
macro_rules! lexical_partial_cmp {
|
|
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
|
|
match ($a).partial_cmp(&$b) {
|
|
Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
|
|
ordering => ordering
|
|
}
|
|
};
|
|
($a:expr, $b:expr) => { ($a).partial_cmp(&$b) };
|
|
}
|
|
|
|
macro_rules! lexical_cmp {
|
|
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
|
|
match ($a).cmp(&$b) {
|
|
Equal => lexical_cmp!($($rest_a, $rest_b),+),
|
|
ordering => ordering
|
|
}
|
|
};
|
|
($a:expr, $b:expr) => { ($a).cmp(&$b) };
|
|
}
|
|
|
|
macro_rules! last_type {
|
|
($a:ident,) => { $a };
|
|
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
|
|
}
|
|
|
|
tuple_impls!(E D C B A Z Y X W V U T);
|