1 | // See core/src/primitive_docs.rs for documentation. |
2 | |
3 | use crate::cmp::Ordering::{self, *}; |
4 | use crate::marker::ConstParamTy; |
5 | use crate::marker::StructuralPartialEq; |
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 = "structural_match" , issue = "31434" )] |
53 | impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+) |
54 | {} |
55 | } |
56 | |
57 | maybe_tuple_doc! { |
58 | $($T)+ @ |
59 | #[unstable(feature = "structural_match" , issue = "31434" )] |
60 | impl<$($T),+> StructuralPartialEq for ($($T,)+) |
61 | {} |
62 | } |
63 | |
64 | maybe_tuple_doc! { |
65 | $($T)+ @ |
66 | #[stable(feature = "rust1" , since = "1.0.0" )] |
67 | impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) |
68 | where |
69 | last_type!($($T,)+): ?Sized |
70 | { |
71 | #[inline] |
72 | fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> { |
73 | lexical_partial_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) |
74 | } |
75 | #[inline] |
76 | fn lt(&self, other: &($($T,)+)) -> bool { |
77 | lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
78 | } |
79 | #[inline] |
80 | fn le(&self, other: &($($T,)+)) -> bool { |
81 | lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
82 | } |
83 | #[inline] |
84 | fn ge(&self, other: &($($T,)+)) -> bool { |
85 | lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
86 | } |
87 | #[inline] |
88 | fn gt(&self, other: &($($T,)+)) -> bool { |
89 | lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+) |
90 | } |
91 | } |
92 | } |
93 | |
94 | maybe_tuple_doc! { |
95 | $($T)+ @ |
96 | #[stable(feature = "rust1" , since = "1.0.0" )] |
97 | impl<$($T: Ord),+> Ord for ($($T,)+) |
98 | where |
99 | last_type!($($T,)+): ?Sized |
100 | { |
101 | #[inline] |
102 | fn cmp(&self, other: &($($T,)+)) -> Ordering { |
103 | lexical_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) |
104 | } |
105 | } |
106 | } |
107 | |
108 | maybe_tuple_doc! { |
109 | $($T)+ @ |
110 | #[stable(feature = "rust1" , since = "1.0.0" )] |
111 | impl<$($T: Default),+> Default for ($($T,)+) { |
112 | #[inline] |
113 | fn default() -> ($($T,)+) { |
114 | ($({ let x: $T = Default::default(); x},)+) |
115 | } |
116 | } |
117 | } |
118 | |
119 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
120 | impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { |
121 | #[inline] |
122 | #[allow(non_snake_case)] |
123 | fn from(array: [T; ${count($T)}]) -> Self { |
124 | let [$($T,)+] = array; |
125 | ($($T,)+) |
126 | } |
127 | } |
128 | |
129 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
130 | impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { |
131 | #[inline] |
132 | #[allow(non_snake_case)] |
133 | fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { |
134 | let ($($T,)+) = tuple; |
135 | [$($T,)+] |
136 | } |
137 | } |
138 | } |
139 | } |
140 | |
141 | // If this is a unary tuple, it adds a doc comment. |
142 | // Otherwise, it hides the docs entirely. |
143 | macro_rules! maybe_tuple_doc { |
144 | ($a:ident @ #[$meta:meta] $item:item) => { |
145 | #[doc(fake_variadic)] |
146 | #[doc = "This trait is implemented for tuples up to twelve items long." ] |
147 | #[$meta] |
148 | $item |
149 | }; |
150 | ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { |
151 | #[doc(hidden)] |
152 | #[$meta] |
153 | $item |
154 | }; |
155 | } |
156 | |
157 | // Constructs an expression that performs a lexical ordering using method `$rel`. |
158 | // The values are interleaved, so the macro invocation for |
159 | // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, |
160 | // a2, b2, a3, b3)` (and similarly for `lexical_cmp`) |
161 | // |
162 | // `$ne_rel` is only used to determine the result after checking that they're |
163 | // not equal, so `lt` and `le` can both just use `Less`. |
164 | macro_rules! lexical_ord { |
165 | ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ |
166 | let c = PartialOrd::partial_cmp(&$a, &$b); |
167 | if c != Some(Equal) { c == Some($ne_rel) } |
168 | else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) } |
169 | }}; |
170 | ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => { |
171 | // Use the specific method for the last element |
172 | PartialOrd::$rel(&$a, &$b) |
173 | }; |
174 | } |
175 | |
176 | macro_rules! lexical_partial_cmp { |
177 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
178 | match ($a).partial_cmp(&$b) { |
179 | Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), |
180 | ordering => ordering |
181 | } |
182 | }; |
183 | ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) }; |
184 | } |
185 | |
186 | macro_rules! lexical_cmp { |
187 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
188 | match ($a).cmp(&$b) { |
189 | Equal => lexical_cmp!($($rest_a, $rest_b),+), |
190 | ordering => ordering |
191 | } |
192 | }; |
193 | ($a:expr, $b:expr) => { ($a).cmp(&$b) }; |
194 | } |
195 | |
196 | macro_rules! last_type { |
197 | ($a:ident,) => { $a }; |
198 | ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; |
199 | } |
200 | |
201 | tuple_impls!(E D C B A Z Y X W V U T); |
202 | |