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 | |