Skip to main content

generic_closure/
lib.rs

1#![doc = include_str!("crate.md")]
2#![doc(test(attr(deny(warnings))))]
3#![no_std]
4#![forbid(unsafe_code)]
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9#[cfg(test)]
10extern crate std;
11
12/// The boxed receiver type used by macro-generated `call_box` methods.
13#[doc(hidden)]
14#[cfg(feature = "alloc")]
15pub use alloc::boxed::Box as __Box;
16
17/// A two-variant sum type used to give different closure bodies one concrete type.
18///
19/// This is re-exported when the default `either` feature is enabled.
20#[cfg(feature = "either")]
21pub use either::Either;
22
23mod closure;
24mod closure_trait;
25
26/// Emits macro-generated items that require the optional `alloc` crate.
27#[doc(hidden)]
28#[cfg(feature = "alloc")]
29#[macro_export]
30macro_rules! __generic_closure_if_alloc {
31    ($($tokens:tt)*) => { $($tokens)* };
32}
33
34#[doc(hidden)]
35#[cfg(not(feature = "alloc"))]
36#[macro_export]
37macro_rules! __generic_closure_if_alloc {
38    ($($tokens:tt)*) => {};
39}
40
41#[doc(hidden)]
42#[cfg(feature = "either")]
43#[macro_export]
44macro_rules! __generic_closure_impl_either {
45    (ref, $trait_name:ident, $type_parameter:ident, [$($bounds:tt)+],
46        [$($predicates:tt)*], [$($argument:ident: $argument_type:ty),*], $output:ty
47    ) => {
48        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
49            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
50        where
51            __GenericClosureEitherLeft: $trait_name,
52            __GenericClosureEitherRight: $trait_name,
53        {
54            fn call<$type_parameter>(&self, $($argument: $argument_type),*) -> $output
55            where
56                $type_parameter: $($bounds)+,
57                $($predicates)*
58            {
59                match self {
60                    $crate::Either::Left(left) => {
61                        $trait_name::call(left, $($argument),*)
62                    }
63                    $crate::Either::Right(right) => {
64                        $trait_name::call(right, $($argument),*)
65                    }
66                }
67            }
68        }
69    };
70
71    (mut, $trait_name:ident, $type_parameter:ident, [$($bounds:tt)+],
72        [$($predicates:tt)*], [$($argument:ident: $argument_type:ty),*], $output:ty
73    ) => {
74        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
75            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
76        where
77            __GenericClosureEitherLeft: $trait_name,
78            __GenericClosureEitherRight: $trait_name,
79        {
80            fn call_mut<$type_parameter>(&mut self, $($argument: $argument_type),*) -> $output
81            where
82                $type_parameter: $($bounds)+,
83                $($predicates)*
84            {
85                match self {
86                    $crate::Either::Left(left) => {
87                        $trait_name::call_mut(left, $($argument),*)
88                    }
89                    $crate::Either::Right(right) => {
90                        $trait_name::call_mut(right, $($argument),*)
91                    }
92                }
93            }
94        }
95    };
96
97    (once, $trait_name:ident, $type_parameter:ident, [$($bounds:tt)+],
98        [$($predicates:tt)*], [$($argument:ident: $argument_type:ty),*], $output:ty
99    ) => {
100        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
101            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
102        where
103            __GenericClosureEitherLeft: $trait_name,
104            __GenericClosureEitherRight: $trait_name,
105        {
106            fn call_once<$type_parameter>(self, $($argument: $argument_type),*) -> $output
107            where
108                $type_parameter: $($bounds)+,
109                $($predicates)*
110            {
111                match self {
112                    $crate::Either::Left(left) => {
113                        $trait_name::call_once(left, $($argument),*)
114                    }
115                    $crate::Either::Right(right) => {
116                        $trait_name::call_once(right, $($argument),*)
117                    }
118                }
119            }
120
121            $crate::__generic_closure_if_alloc! {
122                fn call_box<$type_parameter>(
123                    self: $crate::__Box<Self>, $($argument: $argument_type),*
124                ) -> $output
125                where
126                    $type_parameter: $($bounds)+,
127                    $($predicates)*
128                {
129                    $trait_name::call_once(*self, $($argument),*)
130                }
131            }
132        }
133    };
134}
135
136#[doc(hidden)]
137#[cfg(not(feature = "either"))]
138#[macro_export]
139macro_rules! __generic_closure_impl_either {
140    ($($tokens:tt)*) => {};
141}
142
143#[doc(hidden)]
144#[cfg(feature = "either")]
145#[macro_export]
146macro_rules! __generic_closure_impl_either_nongeneric {
147    (ref, $trait_name:ident, [$($argument:ident: $argument_type:ty),*], $output:ty) => {
148        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
149            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
150        where
151            __GenericClosureEitherLeft: $trait_name,
152            __GenericClosureEitherRight: $trait_name,
153        {
154            fn call(&self, $($argument: $argument_type),*) -> $output {
155                match self {
156                    $crate::Either::Left(left) => {
157                        $trait_name::call(left, $($argument),*)
158                    }
159                    $crate::Either::Right(right) => {
160                        $trait_name::call(right, $($argument),*)
161                    }
162                }
163            }
164        }
165    };
166
167    (mut, $trait_name:ident, [$($argument:ident: $argument_type:ty),*], $output:ty) => {
168        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
169            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
170        where
171            __GenericClosureEitherLeft: $trait_name,
172            __GenericClosureEitherRight: $trait_name,
173        {
174            fn call_mut(&mut self, $($argument: $argument_type),*) -> $output {
175                match self {
176                    $crate::Either::Left(left) => {
177                        $trait_name::call_mut(left, $($argument),*)
178                    }
179                    $crate::Either::Right(right) => {
180                        $trait_name::call_mut(right, $($argument),*)
181                    }
182                }
183            }
184        }
185    };
186
187    (once, $trait_name:ident, [$($argument:ident: $argument_type:ty),*], $output:ty) => {
188        impl<__GenericClosureEitherLeft, __GenericClosureEitherRight> $trait_name
189            for $crate::Either<__GenericClosureEitherLeft, __GenericClosureEitherRight>
190        where
191            __GenericClosureEitherLeft: $trait_name,
192            __GenericClosureEitherRight: $trait_name,
193        {
194            fn call_once(self, $($argument: $argument_type),*) -> $output {
195                match self {
196                    $crate::Either::Left(left) => {
197                        $trait_name::call_once(left, $($argument),*)
198                    }
199                    $crate::Either::Right(right) => {
200                        $trait_name::call_once(right, $($argument),*)
201                    }
202                }
203            }
204
205            $crate::__generic_closure_if_alloc! {
206                fn call_box(
207                    self: $crate::__Box<Self>, $($argument: $argument_type),*
208                ) -> $output {
209                    $trait_name::call_once(*self, $($argument),*)
210                }
211            }
212        }
213    };
214}
215
216#[doc(hidden)]
217#[cfg(not(feature = "either"))]
218#[macro_export]
219macro_rules! __generic_closure_impl_either_nongeneric {
220    ($($tokens:tt)*) => {};
221}
222
223#[cfg(test)]
224mod expansion_lint_tests;