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::{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 | } |
99 | } |
100 | |
101 | maybe_tuple_doc! { |
102 | $($T)+ @ |
103 | #[stable(feature = "rust1" , since = "1.0.0" )] |
104 | impl<$($T: Ord),+> Ord for ($($T,)+) |
105 | where |
106 | last_type!($($T,)+): ?Sized |
107 | { |
108 | #[inline] |
109 | fn cmp(&self, other: &($($T,)+)) -> Ordering { |
110 | lexical_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) |
111 | } |
112 | } |
113 | } |
114 | |
115 | maybe_tuple_doc! { |
116 | $($T)+ @ |
117 | #[stable(feature = "rust1" , since = "1.0.0" )] |
118 | impl<$($T: Default),+> Default for ($($T,)+) { |
119 | #[inline] |
120 | fn default() -> ($($T,)+) { |
121 | ($({ let x: $T = Default::default(); x},)+) |
122 | } |
123 | } |
124 | } |
125 | |
126 | maybe_tuple_doc! { |
127 | $($T)+ @ |
128 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
129 | impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { |
130 | #[inline] |
131 | #[allow(non_snake_case)] |
132 | fn from(array: [T; ${count($T)}]) -> Self { |
133 | let [$($T,)+] = array; |
134 | ($($T,)+) |
135 | } |
136 | } |
137 | } |
138 | |
139 | maybe_tuple_doc! { |
140 | $($T)+ @ |
141 | #[stable(feature = "array_tuple_conv" , since = "1.71.0" )] |
142 | impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { |
143 | #[inline] |
144 | #[allow(non_snake_case)] |
145 | fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { |
146 | let ($($T,)+) = tuple; |
147 | [$($T,)+] |
148 | } |
149 | } |
150 | } |
151 | } |
152 | } |
153 | |
154 | // If this is a unary tuple, it adds a doc comment. |
155 | // Otherwise, it hides the docs entirely. |
156 | macro_rules! maybe_tuple_doc { |
157 | ($a:ident @ #[$meta:meta] $item:item) => { |
158 | #[doc(fake_variadic)] |
159 | #[doc = "This trait is implemented for tuples up to twelve items long." ] |
160 | #[$meta] |
161 | $item |
162 | }; |
163 | ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { |
164 | #[doc(hidden)] |
165 | #[$meta] |
166 | $item |
167 | }; |
168 | } |
169 | |
170 | // Constructs an expression that performs a lexical ordering using method `$rel`. |
171 | // The values are interleaved, so the macro invocation for |
172 | // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, |
173 | // a2, b2, a3, b3)` (and similarly for `lexical_cmp`) |
174 | // |
175 | // `$chain_rel` is the chaining method from `PartialOrd` to use for all but the |
176 | // final value, to produce better results for simple primitives. |
177 | macro_rules! lexical_ord { |
178 | ($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ |
179 | match PartialOrd::$chain_rel(&$a, &$b) { |
180 | Break(val) => val, |
181 | Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+), |
182 | } |
183 | }}; |
184 | ($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => { |
185 | // Use the specific method for the last element |
186 | PartialOrd::$rel(&$a, &$b) |
187 | }; |
188 | } |
189 | |
190 | macro_rules! lexical_partial_cmp { |
191 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
192 | match ($a).partial_cmp(&$b) { |
193 | Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), |
194 | ordering => ordering |
195 | } |
196 | }; |
197 | ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) }; |
198 | } |
199 | |
200 | macro_rules! lexical_cmp { |
201 | ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
202 | match ($a).cmp(&$b) { |
203 | Equal => lexical_cmp!($($rest_a, $rest_b),+), |
204 | ordering => ordering |
205 | } |
206 | }; |
207 | ($a:expr, $b:expr) => { ($a).cmp(&$b) }; |
208 | } |
209 | |
210 | macro_rules! last_type { |
211 | ($a:ident,) => { $a }; |
212 | ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; |
213 | } |
214 | |
215 | tuple_impls!(E D C B A Z Y X W V U T); |
216 | |