]> git.lizzy.rs Git - rust.git/blob - library/core/src/internal_macros.rs
Run the tools builder on all PRs
[rust.git] / library / core / src / internal_macros.rs
1 // implements the unary operator "op &T"
2 // based on "op T" where T is expected to be `Copy`able
3 macro_rules! forward_ref_unop {
4     (impl const $imp:ident, $method:ident for $t:ty) => {
5         forward_ref_unop!(impl const $imp, $method for $t,
6                 #[stable(feature = "rust1", since = "1.0.0")]);
7     };
8     // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
9     (impl const $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
10         #[$attr]
11         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
12         impl const $imp for &$t {
13             type Output = <$t as $imp>::Output;
14
15             #[inline]
16             fn $method(self) -> <$t as $imp>::Output {
17                 $imp::$method(*self)
18             }
19         }
20     };
21     (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
22         #[$attr]
23         impl $imp for &$t {
24             type Output = <$t as $imp>::Output;
25
26             #[inline]
27             fn $method(self) -> <$t as $imp>::Output {
28                 $imp::$method(*self)
29             }
30         }
31     }
32 }
33
34 // implements binary operators "&T op U", "T op &U", "&T op &U"
35 // based on "T op U" where T and U are expected to be `Copy`able
36 macro_rules! forward_ref_binop {
37     (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => {
38         forward_ref_binop!(impl const $imp, $method for $t, $u,
39                 #[stable(feature = "rust1", since = "1.0.0")]);
40     };
41     // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
42     (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
43         #[$attr]
44         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
45         impl<'a> const $imp<$u> for &'a $t {
46             type Output = <$t as $imp<$u>>::Output;
47
48             #[inline]
49             fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
50                 $imp::$method(*self, other)
51             }
52         }
53
54         #[$attr]
55         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
56         impl const $imp<&$u> for $t {
57             type Output = <$t as $imp<$u>>::Output;
58
59             #[inline]
60             fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
61                 $imp::$method(self, *other)
62             }
63         }
64
65         #[$attr]
66         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
67         impl const $imp<&$u> for &$t {
68             type Output = <$t as $imp<$u>>::Output;
69
70             #[inline]
71             fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
72                 $imp::$method(*self, *other)
73             }
74         }
75     };
76     (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
77         #[$attr]
78         impl<'a> $imp<$u> for &'a $t {
79             type Output = <$t as $imp<$u>>::Output;
80
81             #[inline]
82             fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
83                 $imp::$method(*self, other)
84             }
85         }
86
87         #[$attr]
88         impl $imp<&$u> for $t {
89             type Output = <$t as $imp<$u>>::Output;
90
91             #[inline]
92             fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
93                 $imp::$method(self, *other)
94             }
95         }
96
97         #[$attr]
98         impl $imp<&$u> for &$t {
99             type Output = <$t as $imp<$u>>::Output;
100
101             #[inline]
102             fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
103                 $imp::$method(*self, *other)
104             }
105         }
106     }
107 }
108
109 // implements "T op= &U", based on "T op= U"
110 // where U is expected to be `Copy`able
111 macro_rules! forward_ref_op_assign {
112     (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
113         forward_ref_op_assign!(impl $imp, $method for $t, $u,
114                 #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
115     };
116     (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => {
117         forward_ref_op_assign!(impl const $imp, $method for $t, $u,
118                 #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
119     };
120     // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
121     (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
122         #[$attr]
123         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
124         impl const $imp<&$u> for $t {
125             #[inline]
126             fn $method(&mut self, other: &$u) {
127                 $imp::$method(self, *other);
128             }
129         }
130     };
131     (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
132         #[$attr]
133         impl $imp<&$u> for $t {
134             #[inline]
135             fn $method(&mut self, other: &$u) {
136                 $imp::$method(self, *other);
137             }
138         }
139     }
140 }
141
142 /// Create a zero-size type similar to a closure type, but named.
143 macro_rules! impl_fn_for_zst {
144     ($(
145         $( #[$attr: meta] )*
146         struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
147             |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
148             $body: block;
149     )+) => {
150         $(
151             $( #[$attr] )*
152             struct $Name;
153
154             impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
155                 #[inline]
156                 extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
157                     $body
158                 }
159             }
160
161             impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
162                 #[inline]
163                 extern "rust-call" fn call_mut(
164                     &mut self,
165                     ($( $arg, )*): ($( $ArgTy, )*)
166                 ) -> $ReturnTy {
167                     Fn::call(&*self, ($( $arg, )*))
168                 }
169             }
170
171             impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
172                 type Output = $ReturnTy;
173
174                 #[inline]
175                 extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
176                     Fn::call(&self, ($( $arg, )*))
177                 }
178             }
179         )+
180     }
181 }
182
183 /// A macro for defining `#[cfg]` if-else statements.
184 ///
185 /// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
186 /// of `#[cfg]` cases, emitting the implementation which matches first.
187 ///
188 /// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to
189 /// rewrite each clause multiple times.
190 ///
191 /// # Example
192 ///
193 /// ```ignore(cannot-test-this-because-non-exported-macro)
194 /// cfg_if! {
195 ///     if #[cfg(unix)] {
196 ///         fn foo() { /* unix specific functionality */ }
197 ///     } else if #[cfg(target_pointer_width = "32")] {
198 ///         fn foo() { /* non-unix, 32-bit functionality */ }
199 ///     } else {
200 ///         fn foo() { /* fallback implementation */ }
201 ///     }
202 /// }
203 ///
204 /// # fn main() {}
205 /// ```
206 // This is a copy of `cfg_if!` from the `cfg_if` crate.
207 // The recursive invocations should use $crate if this is ever exported.
208 macro_rules! cfg_if {
209     // match if/else chains with a final `else`
210     (
211         $(
212             if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
213         ) else+
214         else { $( $e_tokens:tt )* }
215     ) => {
216         cfg_if! {
217             @__items () ;
218             $(
219                 (( $i_meta ) ( $( $i_tokens )* )) ,
220             )+
221             (() ( $( $e_tokens )* )) ,
222         }
223     };
224
225     // Internal and recursive macro to emit all the items
226     //
227     // Collects all the previous cfgs in a list at the beginning, so they can be
228     // negated. After the semicolon is all the remaining items.
229     (@__items ( $( $_:meta , )* ) ; ) => {};
230     (
231         @__items ( $( $no:meta , )* ) ;
232         (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
233         $( $rest:tt , )*
234     ) => {
235         // Emit all items within one block, applying an appropriate #[cfg]. The
236         // #[cfg] will require all `$yes` matchers specified and must also negate
237         // all previous matchers.
238         #[cfg(all(
239             $( $yes , )?
240             not(any( $( $no ),* ))
241         ))]
242         cfg_if! { @__identity $( $tokens )* }
243
244         // Recurse to emit all other items in `$rest`, and when we do so add all
245         // our `$yes` matchers to the list of `$no` matchers as future emissions
246         // will have to negate everything we just matched as well.
247         cfg_if! {
248             @__items ( $( $no , )* $( $yes , )? ) ;
249             $( $rest , )*
250         }
251     };
252
253     // Internal macro to make __apply work out right for different match types,
254     // because of how macros match/expand stuff.
255     (@__identity $( $tokens:tt )* ) => {
256         $( $tokens )*
257     };
258 }