| 1 | // See core/src/primitive_docs.rs for documentation. |
| 2 | |
| 3 | use crate::cmp::Ordering::{self, *}; |
| 4 | use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy}; |
| 5 | use crate::ops::ControlFlow::{self, Break, Continue}; |
| 6 | |
| 7 | // Recursive macro for implementing n-ary tuple functions and operations |
| 8 | // |
| 9 | // Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C) |
| 10 | // will implement everything for (A, B, C), (A, B) and (A,). |
| 11 | macro_rules! tuple_impls { |
| 12 | // Stopping criteria (1-ary tuple) |
| 13 | ($T:ident) => { |
| 14 | tuple_impls!(@impl $T); |
| 15 | }; |
| 16 | // Running criteria (n-ary tuple, with n >= 2) |
| 17 | ($T:ident $( $U:ident )+) => { |
| 18 | tuple_impls!($( $U )+); |
| 19 | tuple_impls!(@impl $T $( $U )+); |
| 20 | }; |
| 21 | // "Private" internal implementation |
| 22 | (@impl $( $T:ident )+) => { |
| 23 | maybe_tuple_doc! { |
| 24 | $($T)+ @ |
| 25 | #[stable(feature = "rust1" , since = "1.0.0" )] |
| 26 | impl<$($T: PartialEq),+> PartialEq for ($($T,)+) |
| 27 | where |
| 28 | last_type!($($T,)+): ?Sized |
| 29 | { |
| 30 | #[inline] |
| 31 | fn eq(&self, other: &($($T,)+)) -> bool { |
| 32 | $( ${ignore($T)} self.${index()} == other.${index()} )&&+ |
| 33 | } |
| 34 | #[inline] |
| 35 | fn ne(&self, other: &($($T,)+)) -> bool { |
| 36 | $( ${ignore($T)} self.${index()} != other.${index()} )||+ |
| 37 | } |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | maybe_tuple_doc! { |
| 42 | $($T)+ @ |
| 43 | #[stable(feature = "rust1" , since = "1.0.0" )] |
| 44 | impl<$($T: Eq),+> Eq for ($($T,)+) |
| 45 | where |
| 46 | last_type!($($T,)+): ?Sized |
| 47 | {} |
| 48 | } |
| 49 | |
| 50 | maybe_tuple_doc! { |
| 51 | $($T)+ @ |
| 52 | #[unstable(feature = "adt_const_params" , issue = "95174" )] |
| 53 | impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+) |
| 54 | {} |
| 55 | } |
| 56 | |
| 57 | maybe_tuple_doc! { |
| 58 | $($T)+ @ |
| 59 | #[unstable(feature = "unsized_const_params" , issue = "95174" )] |
| 60 | impl<$($T: UnsizedConstParamTy),+> UnsizedConstParamTy for ($($T,)+) |
| 61 | {} |
| 62 | } |
| 63 | |
| 64 | maybe_tuple_doc! { |
| 65 | $($T)+ @ |
| 66 | #[unstable(feature = "structural_match" , issue = "31434" )] |
| 67 | impl<$($T),+> StructuralPartialEq for ($($T,)+) |
| 68 | {} |
| 69 | } |
| 70 | |
| 71 | maybe_tuple_doc! { |
| 72 | $($T)+ @ |
| 73 | #[stable(feature = "rust1" , since = "1.0.0" )] |
| 74 | impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) |
| 75 | where |
| 76 | last_type!($($T,)+): ?Sized |
| 77 | { |
| 78 | #[inline] |
| 79 | fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> { |
| 80 | lexical_partial_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 81 | } |
| 82 | #[inline] |
| 83 | fn lt(&self, other: &($($T,)+)) -> bool { |
| 84 | lexical_ord!(lt, __chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 85 | } |
| 86 | #[inline] |
| 87 | fn le(&self, other: &($($T,)+)) -> bool { |
| 88 | lexical_ord!(le, __chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 89 | } |
| 90 | #[inline] |
| 91 | fn ge(&self, other: &($($T,)+)) -> bool { |
| 92 | lexical_ord!(ge, __chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 93 | } |
| 94 | #[inline] |
| 95 | fn gt(&self, other: &($($T,)+)) -> bool { |
| 96 | lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 97 | } |
| 98 | #[inline] |
| 99 | fn __chaining_lt(&self, other: &($($T,)+)) -> ControlFlow<bool> { |
| 100 | lexical_chain!(__chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 101 | } |
| 102 | #[inline] |
| 103 | fn __chaining_le(&self, other: &($($T,)+)) -> ControlFlow<bool> { |
| 104 | lexical_chain!(__chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 105 | } |
| 106 | #[inline] |
| 107 | fn __chaining_gt(&self, other: &($($T,)+)) -> ControlFlow<bool> { |
| 108 | lexical_chain!(__chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 109 | } |
| 110 | #[inline] |
| 111 | fn __chaining_ge(&self, other: &($($T,)+)) -> ControlFlow<bool> { |
| 112 | lexical_chain!(__chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | maybe_tuple_doc! { |
| 118 | $($T)+ @ |
| 119 | #[stable(feature = "rust1" , since = "1.0.0" )] |
| 120 | impl<$($T: Ord),+> Ord for ($($T,)+) |
| 121 | where |
| 122 | last_type!($($T,)+): ?Sized |
| 123 | { |
| 124 | #[inline] |
| 125 | fn cmp(&self, other: &($($T,)+)) -> Ordering { |
| 126 | lexical_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | maybe_tuple_doc! { |
| 132 | $($T)+ @ |
| 133 | #[stable(feature = "rust1" , since = "1.0.0" )] |
| 134 | impl<$($T: Default),+> Default for ($($T,)+) { |
| 135 | #[inline] |
| 136 | fn default() -> ($($T,)+) { |
| 137 | ($({ let x: $T = Default::default(); x},)+) |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | maybe_tuple_doc! { |
| 143 | $($T)+ @ |
| 144 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
| 145 | impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { |
| 146 | #[inline] |
| 147 | #[allow(non_snake_case)] |
| 148 | fn from(array: [T; ${count($T)}]) -> Self { |
| 149 | let [$($T,)+] = array; |
| 150 | ($($T,)+) |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | maybe_tuple_doc! { |
| 156 | $($T)+ @ |
| 157 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
| 158 | impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { |
| 159 | #[inline] |
| 160 | #[allow(non_snake_case)] |
| 161 | fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { |
| 162 | let ($($T,)+) = tuple; |
| 163 | [$($T,)+] |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | // If this is a unary tuple, it adds a doc comment. |
| 171 | // Otherwise, it hides the docs entirely. |
| 172 | macro_rules! maybe_tuple_doc { |
| 173 | ($a:ident @ #[$meta:meta] $item:item) => { |
| 174 | #[doc(fake_variadic)] |
| 175 | #[doc = "This trait is implemented for tuples up to twelve items long." ] |
| 176 | #[$meta] |
| 177 | $item |
| 178 | }; |
| 179 | ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { |
| 180 | #[doc(hidden)] |
| 181 | #[$meta] |
| 182 | $item |
| 183 | }; |
| 184 | } |
| 185 | |
| 186 | // Constructs an expression that performs a lexical ordering using method `$rel`. |
| 187 | // The values are interleaved, so the macro invocation for |
| 188 | // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, |
| 189 | // a2, b2, a3, b3)` (and similarly for `lexical_cmp`) |
| 190 | // |
| 191 | // `$chain_rel` is the chaining method from `PartialOrd` to use for all but the |
| 192 | // final value, to produce better results for simple primitives. |
| 193 | macro_rules! lexical_ord { |
| 194 | ($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ |
| 195 | match PartialOrd::$chain_rel(&$a, &$b) { |
| 196 | Break(val) => val, |
| 197 | Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+), |
| 198 | } |
| 199 | }}; |
| 200 | ($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => { |
| 201 | // Use the specific method for the last element |
| 202 | PartialOrd::$rel(&$a, &$b) |
| 203 | }; |
| 204 | } |
| 205 | |
| 206 | // Same parameter interleaving as `lexical_ord` above |
| 207 | macro_rules! lexical_chain { |
| 208 | ($chain_rel: ident, $a:expr, $b:expr $(,$rest_a:expr, $rest_b:expr)*) => {{ |
| 209 | PartialOrd::$chain_rel(&$a, &$b)?; |
| 210 | lexical_chain!($chain_rel $(,$rest_a, $rest_b)*) |
| 211 | }}; |
| 212 | ($chain_rel: ident) => { |
| 213 | Continue(()) |
| 214 | }; |
| 215 | } |
| 216 | |
| 217 | macro_rules! lexical_partial_cmp { |
| 218 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
| 219 | match ($a).partial_cmp(&$b) { |
| 220 | Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), |
| 221 | ordering => ordering |
| 222 | } |
| 223 | }; |
| 224 | ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) }; |
| 225 | } |
| 226 | |
| 227 | macro_rules! lexical_cmp { |
| 228 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
| 229 | match ($a).cmp(&$b) { |
| 230 | Equal => lexical_cmp!($($rest_a, $rest_b),+), |
| 231 | ordering => ordering |
| 232 | } |
| 233 | }; |
| 234 | ($a:expr, $b:expr) => { ($a).cmp(&$b) }; |
| 235 | } |
| 236 | |
| 237 | macro_rules! last_type { |
| 238 | ($a:ident,) => { $a }; |
| 239 | ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; |
| 240 | } |
| 241 | |
| 242 | tuple_impls!(E D C B A Z Y X W V U T); |
| 243 | |