core/
internal_macros.rs

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