Skip to main content

newtype_ops/
lib.rs

1// Copyright 2016 Michael Lamparski
2//
3// Licensed under WTFPL-2.0 (see file COPYING).
4
5//! # newtype-ops
6//!
7//! An attempt to provide a macro for mass-forwarding impls for newtypes.
8//!
9//! Is currently "usable" for wrappers around primitives and some awkward special cases.
10//!
11//! There is comprehensive documentation on the [`newtype_ops`] macro.
12
13#![no_std]
14
15#![cfg_attr(feature = "debug-trace-macros", feature(trace_macros))]
16#[cfg(feature = "debug-trace-macros")] trace_macros!(true);
17
18/// A macro for mass-forwarding operator impls on newtypes.
19///
20/// Some examples:
21///
22/// ```rust
23/// use newtype_ops::newtype_ops;
24///
25/// // derive everything under the sun
26/// pub struct Foo(pub i32);
27/// newtype_ops! { [Foo] integer {:=} {^&}Self {^&}{Self i32} }
28///
29/// // derive everything under the sun for floats
30/// pub struct Bar(pub f32);
31/// newtype_ops! { [Bar] arithmetic {:=} {^&}Self {^&}{Self f32} }
32/// ```
33
34/// These two impls are equivalent to this:
35///
36/// ```rust
37/// # use newtype_ops::newtype_ops;
38/// # pub struct Foo(pub i32);
39/// # pub struct Bar(pub f32);
40/// newtype_ops! { [Foo] {add sub mul div rem neg
41///                       not bitand bitor bitxor} {:=} {^&}Self {^&}{Self i32} }
42/// newtype_ops! { [Bar] {add sub mul div rem neg} {:=} {^&}Self {^&}{Self f32} }
43/// ```
44
45/// Which are in turn equivalent to this;
46/// every braced portion is expanded in a cartesian product of the tokens inside.
47/// To give you a feel for what the various parts of the syntax stand for, the
48/// impls are labeled in comments.
49///
50/// ```rust
51/// # use newtype_ops::newtype_ops;
52/// # pub struct Foo(pub i32);
53/// # pub struct Bar(pub f32);
54/// newtype_ops! { [Foo] add : ^Self ^Self } // impl Add<Foo>  for Foo { ... }
55/// newtype_ops! { [Foo] add : ^Self ^i32  } // impl Add<i32>  for Foo { ... }
56/// newtype_ops! { [Foo] add : ^Self &Self } // impl Add<&Foo> for Foo { ... }
57/// newtype_ops! { [Foo] add : ^Self &i32  } // impl Add<&i32> for Foo { ... }
58/// newtype_ops! { [Foo] add : &Self ^Self } // impl Add<Foo>  for &Foo { ... }
59/// newtype_ops! { [Foo] add : &Self ^i32  } // impl Add<i32>  for &Foo { ... }
60/// newtype_ops! { [Foo] add : &Self &Self } // impl Add<&Foo> for &Foo { ... }
61/// newtype_ops! { [Foo] add : &Self &i32  } // impl Add<&i32> for &Foo { ... }
62/// newtype_ops! { [Foo] add = ^Self ^Self } // impl AddAssign<Foo> for Foo { ... }
63/// newtype_ops! { [Foo] add = ^Self ^i32  } // impl AddAssign<i32> for Foo { ... }
64/// newtype_ops! { [Foo] add = ^Self &Self } // Silently ignored [b]
65/// newtype_ops! { [Foo] add = ^Self &i32  } // Silently ignored [b]
66/// newtype_ops! { [Foo] add = &Self ^Self } // Silently ignored [a]
67/// newtype_ops! { [Foo] add = &Self ^i32  } // Silently ignored [a]
68/// newtype_ops! { [Foo] add = &Self &Self } // Silently ignored [a]
69/// newtype_ops! { [Foo] add = &Self &i32  } // Silently ignored [a]
70/// // ... Sub impls ...
71/// // ... Mul impls ...
72/// // ... Div impls ...
73/// // ... Rem impls ...
74/// newtype_ops! { [Foo] neg : ^Self ^Self } // impl Neg for Foo { ... }
75/// newtype_ops! { [Foo] neg : ^Self ^i32  } // Silently ignored [c]
76/// newtype_ops! { [Foo] neg : ^Self &Self } // Silently ignored [c]
77/// newtype_ops! { [Foo] neg : ^Self &i32  } // Silently ignored [c]
78/// newtype_ops! { [Foo] neg : &Self ^Self } // impl Neg for &Foo { ... }
79/// newtype_ops! { [Foo] neg : &Self ^i32  } // Silently ignored [c]
80/// newtype_ops! { [Foo] neg : &Self &Self } // Silently ignored [c]
81/// newtype_ops! { [Foo] neg : &Self &i32  } // Silently ignored [c]
82/// newtype_ops! { [Foo] neg = ^Self ^Self } // Silently ignored [a]
83/// newtype_ops! { [Foo] neg = ^Self ^i32  } // Silently ignored [a]
84/// newtype_ops! { [Foo] neg = ^Self &Self } // Silently ignored [a]
85/// newtype_ops! { [Foo] neg = ^Self &i32  } // Silently ignored [a]
86/// newtype_ops! { [Foo] neg = &Self ^Self } // Silently ignored [a]
87/// newtype_ops! { [Foo] neg = &Self ^i32  } // Silently ignored [a]
88/// newtype_ops! { [Foo] neg = &Self &Self } // Silently ignored [a]
89/// newtype_ops! { [Foo] neg = &Self &i32  } // Silently ignored [a]
90/// ```
91
92/// **_Holy blazing swordfish,_** you should reply,
93/// _why are so many impls silently ignored?_
94///
95/// Well, a couple of reasons.  They're labeled:
96///
97/// * `[a]`: **They're nonsense/impossible,** yet cartesian products generate them.
98/// * `[b]`: **For not very good reasons.** <br />
99///          `AddAssign<&Bar>` and `AddAssign<&i32>` are certainly possible.
100///          However, the majority of newtype wrappers are likely around primitives,
101///          and primitive types are mysteriously missing `XyzAssign` impls for borrowed args.
102///          Simply put, I forbade these so that the invocation at the top of the page *works.*
103/// * `[c]`: **Shortcomings in implementation.** <br />
104///          Obviously `Neg` doesn't care about an argument type,
105///          but gets paired with a whole bunch of them anyways
106///          thanks to the cartesian product design.
107///          The labeled invocations are thus ignored to avoid generating
108///          multiple conflicting impls.
109
110// The next line -- an empty '///' -- seems to be necessary for the subheading to appear...
111///
112/// ## Other notes:
113///
114/// There are four words which stand in for **groups of operators:**
115///
116/// * `arithmetic` is equivalent to `{add sub mul div rem neg}`
117/// * `arith_ring` is equivalent to `{add sub mul neg}`
118/// * `bitwise` is equivalent to `{bitand bitor bitxor not}`
119/// * `integer` is equivalent to `{arithmetic bitwise}`
120///
121/// There are also **word equivalents** for `:` (`normal`) and `=` (`assign`).
122///
123/// **There are deliberately NOT operator shortcuts** such as `+` for `add`,
124/// because it is too easy to accidentally embed a comment delimiter: `{+-*/%}`
125///
126/// **The caret `^` before value types can be omitted.**
127/// Its raison d'être is to give you something to put in a cartesian product.
128///
129/// ```rust
130/// # use newtype_ops::newtype_ops;
131/// # pub struct Foo(pub i32);
132/// # pub struct Bar(pub f32);
133/// newtype_ops! { [Bar] add : Self Self }
134/// ```
135
136/// You can omit the final type, in which case it is inferred to be `Self`.
137/// This is for the sake of unary ops, but it currently also affects others...
138///
139/// ```rust
140/// # use newtype_ops::newtype_ops;
141/// # pub struct Bar(pub f32);
142/// newtype_ops! { [Bar] neg : Self } // Allowed
143/// newtype_ops! { [Bar] add : Self } // Also allowed (but discouraged; may change)
144/// ```
145
146/// The implemented type is bracketed (a) to help parse it,
147/// and (b) so that it can use a cartesian product,
148/// which currently operates specifically on token trees.
149/// E.g. this is valid:
150///
151/// ```rust
152/// # use newtype_ops::newtype_ops;
153/// pub mod foo {
154///     pub struct Foo(pub i32);
155/// }
156/// pub struct Bar(pub i32);
157/// pub struct Generic<T>(T);
158///
159/// newtype_ops! { {[foo::Foo] [Bar] [Generic<i32>]} arithmetic {:=} Self Self }
160/// ```
161
162/// The output type can also be anything arbitrary like `foo::Foo` or `Generic<i32>`,
163/// so long as `self.0` (`&self.0` for `&Self` receivers) implements `Add` for that type.
164/// However, be careful with cartesian products;
165/// `{Self i32}` only works because `Self` and `i32` are individual token trees.
166/// `{foo::Foo Generic<i32>}` will fail miserably.
167///
168/// The `Index`, `Deref`, and `Fn` trait hierarchies are considered in-scope for future additions,
169/// but hell if I know how to fit them into the existing interface.
170
171#[macro_export(local_inner_macros)]
172macro_rules! newtype_ops {
173    ($($rest:tt)*) => { newtype_ops__!{ @product::next($($rest)*) -> () }};
174}
175
176#[macro_export(local_inner_macros)]
177#[doc(hidden)]
178macro_rules! newtype_ops__ {
179
180    //----------------------
181    // @product:  Handles the behavior of {} products
182
183    (@product::next({$($token:tt)+} $($rest:tt)*) -> $args:tt) => {
184        newtype_ops__!{ @product::unpack({$($token)+} $($rest)*) -> $args }};
185    (@product::next( $token:tt $($rest:tt)*) -> $args:tt) => {
186        newtype_ops__!{ @product::single($token $($rest)*) -> $args }};
187    (@product::next() -> $args:tt) => {
188        newtype_ops__!{ @interpret$args }};
189
190    // Add one token to the argument list.
191    (@product::single($token:tt $($rest:tt)*) -> ($($args:tt)*)) => {
192        newtype_ops__!{ @product::next($($rest)*) -> ($($args)* $token) }};
193
194    // Each direct product in the invocation incurs a fixed number of recursions
195    //   as we replicate things to the correct depth.
196    // Compress all unparsed text into a single tt so we can match it without a repetition.
197    (@product::unpack({$($token:tt)*} $($rest:tt)*) -> $args:tt) => {
198        newtype_ops__!{ @product::unpack_2({$($token)*} [$($rest)*]) -> $args }};
199    // Replicate macro for each token:
200    (@product::unpack_2({$($token:tt)*} $rest:tt) -> $args:tt) => {
201        $( newtype_ops__!{ @product::unpack_3($token $rest) -> $args } )* };
202    // Expand the unparsed arguments back to normal.
203    // (using single instead of next avoids reparsing a nested {} as another direct product,
204    //  as I am uncertain that such behavior would be useful)
205    (@product::unpack_3($token:tt [$($rest:tt)*]) -> $args:tt) => {
206        newtype_ops__!{ @product::single($token $($rest)*) -> $args }};
207
208    //----------------------
209    // @interpret:  Parses individual arguments, expands internally-defined groups.
210
211    (@interpret($($rest:tt)*)) => { newtype_ops__!{ @interpret::type($($rest)*) -> () }};
212
213    (@interpret::type([$($T:tt)*] $($rest:tt)*) -> ($($args:tt)*)) => {
214        newtype_ops__!{ @interpret::oper($($rest)*) -> ($($args)* {value_ty:[$($T)*]}) }};
215
216    (@interpret::oper(arithmetic $($rest:tt)*) -> ($($args:tt)*)) => {
217        newtype_ops__!{ @interpret::oper(add $($rest)*) -> ($($args)*) }
218        newtype_ops__!{ @interpret::oper(sub $($rest)*) -> ($($args)*) }
219        newtype_ops__!{ @interpret::oper(mul $($rest)*) -> ($($args)*) }
220        newtype_ops__!{ @interpret::oper(div $($rest)*) -> ($($args)*) }
221        newtype_ops__!{ @interpret::oper(rem $($rest)*) -> ($($args)*) }
222        newtype_ops__!{ @interpret::oper(neg $($rest)*) -> ($($args)*) }
223    };
224
225    // API NOTE:
226    //  Purposefully not named 'all' because such a name would also imply support for Index,
227    //  Deref, and the Fn traits if I ever get to adding them. (and an option which provides
228    //  both e.g. Mul and Index will probably have no applicable types)
229    (@interpret::oper(integer $($rest:tt)*) -> ($($args:tt)*)) => {
230        newtype_ops__!{ @interpret::oper(bitand $($rest)*) -> ($($args)*) }
231        newtype_ops__!{ @interpret::oper(bitor  $($rest)*) -> ($($args)*) }
232        newtype_ops__!{ @interpret::oper(bitxor $($rest)*) -> ($($args)*) }
233        newtype_ops__!{ @interpret::oper(not $($rest)*) -> ($($args)*) }
234        newtype_ops__!{ @interpret::oper(add $($rest)*) -> ($($args)*) }
235        newtype_ops__!{ @interpret::oper(sub $($rest)*) -> ($($args)*) }
236        newtype_ops__!{ @interpret::oper(mul $($rest)*) -> ($($args)*) }
237        newtype_ops__!{ @interpret::oper(div $($rest)*) -> ($($args)*) }
238        newtype_ops__!{ @interpret::oper(rem $($rest)*) -> ($($args)*) }
239        newtype_ops__!{ @interpret::oper(neg $($rest)*) -> ($($args)*) }
240    };
241
242    (@interpret::oper(arith_ring $($rest:tt)*) -> ($($args:tt)*)) => {
243        newtype_ops__!{ @interpret::oper(add $($rest)*) -> ($($args)*) }
244        newtype_ops__!{ @interpret::oper(sub $($rest)*) -> ($($args)*) }
245        newtype_ops__!{ @interpret::oper(mul $($rest)*) -> ($($args)*) }
246        newtype_ops__!{ @interpret::oper(neg $($rest)*) -> ($($args)*) }
247    };
248
249    (@interpret::oper(bitwise $($rest:tt)*) -> ($($args:tt)*)) => {
250        newtype_ops__!{ @interpret::oper(bitand $($rest)*) -> ($($args)*) }
251        newtype_ops__!{ @interpret::oper(bitor  $($rest)*) -> ($($args)*) }
252        newtype_ops__!{ @interpret::oper(bitxor $($rest)*) -> ($($args)*) }
253        newtype_ops__!{ @interpret::oper(not    $($rest)*) -> ($($args)*) }
254    };
255
256    // NOTE: The original plan was to allow +*-/%^&| here but it is too easy to
257    //       accidentally put * and / together and end up making your life hell. :V
258    //
259    // Commas would be nice, e.g. {+,-,*,/,%,^,|,&} but it's tough to fit that into
260    // @product() without exposing some cleverly-hidden warts and/or enabling unbounded
261    // recursion.
262    (@interpret::oper(add $($rest:tt)*) -> ($($args:tt)*)) => {
263        newtype_ops__!{ @interpret::mode($($rest)*) -> (
264            $($args)* {kind:binary}
265            {traits:[[::core::ops::Add][::core::ops::AddAssign]]}
266            {methods:[[add][add_assign]]}
267        )}};
268
269    (@interpret::oper(sub $($rest:tt)*) -> ($($args:tt)*)) => {
270        newtype_ops__!{ @interpret::mode($($rest)*) -> (
271            $($args)* {kind:binary}
272            {traits:[[::core::ops::Sub][::core::ops::SubAssign]]}
273            {methods:[[sub][sub_assign]]}
274        )}};
275
276    (@interpret::oper(mul $($rest:tt)*) -> ($($args:tt)*)) => {
277        newtype_ops__!{ @interpret::mode($($rest)*) -> (
278            $($args)* {kind:binary}
279            {traits:[[::core::ops::Mul][::core::ops::MulAssign]]}
280            {methods:[[mul][mul_assign]]}
281        )}};
282
283    (@interpret::oper(div $($rest:tt)*) -> ($($args:tt)*)) => {
284        newtype_ops__!{ @interpret::mode($($rest)*) -> (
285            $($args)* {kind:binary}
286            {traits:[[::core::ops::Div][::core::ops::DivAssign]]}
287            {methods:[[div][div_assign]]}
288        )}};
289
290    (@interpret::oper(rem $($rest:tt)*) -> ($($args:tt)*)) => {
291        newtype_ops__!{ @interpret::mode($($rest)*) -> (
292            $($args)* {kind:binary}
293            {traits:[[::core::ops::Rem][::core::ops::RemAssign]]}
294            {methods:[[rem][rem_assign]]}
295        )}};
296
297    (@interpret::oper(neg $($rest:tt)*) -> ($($args:tt)*)) => {
298        newtype_ops__!{ @interpret::mode($($rest)*) -> (
299            $($args)* {kind:unary}
300            {traits:[[::core::ops::Neg]]}
301            {methods:[[neg]]}
302        )}};
303
304    (@interpret::oper(bitand $($rest:tt)*) -> ($($args:tt)*)) => {
305        newtype_ops__!{ @interpret::mode($($rest)*) -> (
306            $($args)* {kind:binary}
307            {traits:[[::core::ops::BitAnd][::core::ops::BitAndAssign]]}
308            {methods:[[bitand][bitand_assign]]}
309        )}};
310
311    (@interpret::oper(bitor $($rest:tt)*) -> ($($args:tt)*)) => {
312        newtype_ops__!{ @interpret::mode($($rest)*) -> (
313            $($args)* {kind:binary}
314            {traits:[[::core::ops::BitOr][::core::ops::BitOrAssign]]}
315            {methods:[[bitor][bitor_assign]]}
316        )}};
317
318    (@interpret::oper(bitxor $($rest:tt)*) -> ($($args:tt)*)) => {
319        newtype_ops__!{ @interpret::mode($($rest)*) -> (
320            $($args)* {kind:binary}
321            {traits:[[::core::ops::BitXor][::core::ops::BitXorAssign]]}
322            {methods:[[bitxor][bitxor_assign]]}
323        )}};
324
325    (@interpret::oper(not $($rest:tt)*) -> ($($args:tt)*)) => {
326        newtype_ops__!{ @interpret::mode($($rest)*) -> (
327            $($args)* {kind:unary}
328            {traits:[[::core::ops::Not]]}
329            {methods:[[not]]}
330        )}};
331
332    // or 'pure', but that's a reserved keyword and some editors give it scare-highlighting
333    (@interpret::mode(normal $($rest:tt)*) -> ($($args:tt)*)) => {
334        newtype_ops__!{ @interpret::self($($rest)*) -> ($($args)* {mode:normal}) }};
335    (@interpret::mode(assign $($rest:tt)*) -> ($($args:tt)*)) => {
336        newtype_ops__!{ @interpret::self($($rest)*) -> ($($args)* {mode:assign}) }};
337    (@interpret::mode(: $($rest:tt)*) -> ($($args:tt)*)) => {
338        newtype_ops__!{ @interpret::self($($rest)*) -> ($($args)* {mode:normal}) }};
339    (@interpret::mode(= $($rest:tt)*) -> ($($args:tt)*)) => {
340        newtype_ops__!{ @interpret::self($($rest)*) -> ($($args)* {mode:assign}) }};
341
342    (@interpret::self(&Self $($rest:tt)*) -> ($($args:tt)*)) => {
343        newtype_ops__!{ @interpret::other($($rest)*) -> ($($args)* {recv_form:[&x.0]}) }};
344    (@interpret::self(^Self $($rest:tt)*) -> ($($args:tt)*)) => {
345        newtype_ops__!{ @interpret::other($($rest)*) -> ($($args)* {recv_form:[x.0]}) }};
346    (@interpret::self(Self $($rest:tt)*) -> ($($args:tt)*)) => {
347        newtype_ops__!{ @interpret::other($($rest)*) -> ($($args)* {recv_form:[x.0]}) }};
348
349    // NOTE: here, we take advantage of the fact that the second type
350    //       is the final argument in two ways:
351    //  1. To allow it to be easily omitted for unary ops.
352    //  2. To allow it to be an arbitrary type without requiring delimiters around it.
353    //     (the first type is always Self, so no inconsistency is felt)
354    // FIXME: This is a sucky thing to take advantage of because it
355    //        means we can't do cartesian product.
356
357    // operations between two newtypes
358    (@interpret::other(&Self) -> ($($args:tt)*)) => {
359        newtype_ops__!{ @postprocess($($args)* {arg:[#ref]} {arg_form:[&x.0]}) }};
360    (@interpret::other(^Self) -> ($($args:tt)*)) => {
361        newtype_ops__!{ @postprocess($($args)* {arg:[#value]} {arg_form:[x.0]}) }};
362    (@interpret::other(Self) -> ($($args:tt)*)) => {
363        newtype_ops__!{ @postprocess($($args)* {arg:[#value]} {arg_form:[x.0]}) }};
364    (@interpret::other() -> ($($args:tt)*)) => {
365        newtype_ops__!{ @postprocess($($args)* {arg:[#value]} {arg_form:[x.0]}) }};
366    // operations between newtype and another type U for which (T or &T):Add<U>.
367    (@interpret::other(^$($rest:tt)+) -> ($($args:tt)*)) => {
368        newtype_ops__!{ @postprocess($($args)* {arg:[$($rest)*]} {arg_form:[x]}) }};
369    (@interpret::other($($rest:tt)+) -> ($($args:tt)*)) => {
370        newtype_ops__!{ @postprocess($($args)* {arg:[$($rest)*]} {arg_form:[x]}) }};
371
372    //----------------------
373    // @postprocess
374
375    (@postprocess(
376        $value_ty:tt $kind:tt $traits:tt $methods:tt $mode:tt $recv_form:tt $arg:tt $arg_form:tt
377    )) => {
378        newtype_ops__!{ @postprocess::blacklist(
379            [$mode $kind $recv_form $arg_form $arg] // for @postprocess::blacklist
380            [$arg $value_ty $recv_form]             // for @postprocess::true_types
381            $traits $methods $recv_form $arg_form // initial list for @postprocess::almost_there
382        ) }
383    };
384
385    // HACK: some arguments render other arguments inert; for instance, an impl for 'neg'
386    //       has no argument type.  Bad combos do result from the cartesian product syntax,
387    //       and unfortunately we cannot just ignore the nonsensical arguments because then
388    //       we wil end up producing multiple conflicting impls.
389    // Therefore, for each case where an argument is rendered nonsensical, only one of its
390    // possible values will be accepted.  Anything else is—with apologies—silently ignored.
391
392    // Make 'unary' require 'normal'
393    // At the same time, fold mode into kind for three possible values: unary, binary, assign
394    (@postprocess::blacklist([{mode:assign} {kind:unary}  $($more:tt)*] $($rest:tt)*)) => {
395        };
396    (@postprocess::blacklist([{mode:assign} {kind:binary} $($more:tt)*] $($rest:tt)*)) => {
397        newtype_ops__!{ @postprocess::blacklist([{kind:assign} $($more)*] $($rest)*) }};
398    (@postprocess::blacklist([{mode:normal} {kind:unary} $($more:tt)*] $($rest:tt)*)) => {
399        newtype_ops__!{ @postprocess::blacklist([{kind:unary} $($more)*] $($rest)*) }};
400    (@postprocess::blacklist([{mode:normal} {kind:binary} $($more:tt)*] $($rest:tt)*)) => {
401        newtype_ops__!{ @postprocess::blacklist([{kind:binary} $($more)*] $($rest)*) }};
402
403    // Make assign require a '^Self' receiver  (form = [x.0])
404    (@postprocess::blacklist([{kind:assign} {recv_form:[&x.0]} $arg_form:tt $arg:tt] $($rest:tt)*)) => { };
405    // Make 'unary' require a '^Self' argument
406    (@postprocess::blacklist([{kind:unary} $recv_form:tt {arg_form:[&x.0]} $arg:tt] $($rest:tt)*)) => { };
407    (@postprocess::blacklist([{kind:unary} $recv_form:tt {arg_form:[x]}    $arg:tt] $($rest:tt)*)) => { };
408
409    // FIXME: Awful hack:
410    // We deliberately ignore TraitAssign impls where the argument is borrowed, to make mass impls
411    //  involving primitive wrapped types easier. (the standard library primitives lack impls
412    //  for AddAssign<&Self> and etc.)
413    // This obviously has nasty consequences for newtype wrappers around non-primitives for which
414    //  such impls potentially *could* be valid.
415    (@postprocess::blacklist([{kind:assign} $recv_form:tt $arg_form:tt {arg:[#ref]}] $($rest:tt)*)) => { };
416    (@postprocess::blacklist([{kind:assign} $recv_form:tt $arg_form:tt {arg:[&$($arg:tt)+]}] $($rest:tt)*)) => { };
417
418    (@postprocess::blacklist([{kind:$kind:tt} $($dropped:tt)*] $($rest:tt)*)) => {
419        newtype_ops__!{ @postprocess::true_types($($rest)* {kind: $kind}) }};
420
421    // Replace the #value and #ref placeholders with Self-based types
422    (@postprocess::true_types(
423        [{arg:[#value]} {value_ty:[$($T:tt)*]} $recv_form:tt] $($rest:tt)*
424    )) => { newtype_ops__!{ @postprocess::true_types::2(
425        [{value_ty:[$($T)*]} $recv_form {arg:[$($T)*]}] $($rest)*
426    )}};
427    (@postprocess::true_types(
428        [{arg:[#ref]} {value_ty:[$($T:tt)*]} $recv_form:tt] $($rest:tt)*
429    )) => { newtype_ops__!{ @postprocess::true_types::2(
430        [{value_ty:[$($T)*]} $recv_form {arg:[&$($T)*]}] $($rest)*
431    )}};
432    (@postprocess::true_types(
433        [{arg:[$($arg:tt)*]} {value_ty:[$($T:tt)*]} $recv_form:tt] $($rest:tt)*
434    )) => { newtype_ops__!{ @postprocess::true_types::2(
435        [{value_ty:[$($T)*]} $recv_form {arg:[$($arg)*]}] $($rest)*
436    )}};
437
438    // Generate lifetimes.
439    (@postprocess::true_types::2(
440        [{value_ty:[$($T:tt)*]} {recv_form:[&$($recv_form:tt)*]} {arg:[&$($arg:tt)*]}] $($rest:tt)*
441    )) => {
442        newtype_ops__!{ @postprocess::almost_there(
443            $($rest)* {tpars:[<'a,'b>]} {recv:[&'a $($T)*]} {arg:[&'b $($arg)*]} {out:[$($T)*]}
444        )}
445    };
446
447    (@postprocess::true_types::2(
448        [{value_ty:[$($T:tt)*]} {recv_form:[&$($recv_form:tt)*]} {arg:[$($arg:tt)*]}] $($rest:tt)*
449    )) => {
450        newtype_ops__!{ @postprocess::almost_there(
451            $($rest)* {tpars:[<'a>]} {recv:[&'a $($T)*]} {arg:[$($arg)*]} {out:[$($T)*]}
452        )}
453    };
454
455    (@postprocess::true_types::2(
456        [{value_ty:[$($T:tt)*]} {recv_form:[$($recv_form:tt)*]} {arg:[&$($arg:tt)*]}] $($rest:tt)*
457    )) => {
458        newtype_ops__!{ @postprocess::almost_there(
459            $($rest)* {tpars:[<'b>]} {recv:[$($T)*]} {arg:[&'b $($arg)*]} {out:[$($T)*]}
460        )}
461    };
462
463    (@postprocess::true_types::2(
464        [{value_ty:[$($T:tt)*]} {recv_form:[$($recv_form:tt)*]} {arg:[$($arg:tt)*]}] $($rest:tt)*
465    )) => {
466        newtype_ops__!{ @postprocess::almost_there(
467            $($rest)* {tpars:[]} {recv:[$($T)*]} {arg:[$($arg)*]} {out:[$($T)*]}
468        )}
469    };
470
471    // at this stage we explicitly match the labels in each argument to ensure everything
472    //  in order (literally)
473    (@postprocess::almost_there(
474        {traits:$traits:tt} {methods:$methods:tt}
475        {recv_form:$recv_form:tt} {arg_form:$arg_form:tt}
476        {kind:$kind:tt}                                               // from blacklist
477        {tpars:$tpars:tt} {recv:$Recv:tt} {arg:$Arg:tt} {out:$Out:tt} // from true_types
478    )) => {
479        newtype_ops__!{
480            @impl::$kind
481            traits:$traits methods:$methods
482            tpars:$tpars recv:$Recv arg:$Arg out:$Out
483            forms:[$recv_form $arg_form]
484        }
485    };
486
487    (@impl::unary
488        traits:[[$($Trait:tt)*]]
489        methods:[[$meth:ident]]
490        tpars:[$($tpars:tt)*] recv:[$Recv:ty] arg:$_Arg:tt out:[$Out:path]
491        forms:[[$($form1:tt)*] $_form2:tt]
492    ) => {
493        impl$($tpars)* $($Trait)* for $Recv {
494            type Output = $Out;
495            fn $meth(self) -> $Out {
496                let this = self;
497                $Out(
498                    newtype_ops__!(@helper::delegate [$($form1)*] [this] [0]).$meth()
499                )
500            }
501        }
502    };
503
504    (@impl::binary
505        traits:[[$($Trait:tt)*] $_TraitAssign:tt]
506        methods:[[$meth:ident] $_meth_assign:tt]
507        tpars:[$($tpars:tt)*] recv:[$Recv:ty] arg:[$Arg:ty] out:[$Out:path]
508        forms:[[$($form1:tt)*][$($form2:tt)*]]
509    ) => {
510        impl$($tpars)* $($Trait)*<$Arg> for $Recv {
511            type Output = $Out;
512            fn $meth(self, other: $Arg) -> $Out {
513                let this = self;
514                $Out(
515                    newtype_ops__!(@helper::delegate [$($form1)*]  [this] [0])
516                    .$meth(
517                    newtype_ops__!(@helper::delegate [$($form2)*] [other] [0])
518                    )
519                )
520            }
521        }
522    };
523
524    (@impl::assign
525        traits:[$_Trait:tt [$($TraitAssign:tt)*]]
526        methods:[$_meth:tt [$meth_assign:ident]]
527        tpars:[$($tpars:tt)*] recv:[$Recv:ty] arg:[$Arg:ty] out:$_Out:tt
528        forms:[$_form1:tt [$($form2:tt)*]]
529    ) => {
530        impl$($tpars)* $($TraitAssign)*<$Arg> for $Recv {
531            fn $meth_assign(&mut self, other: $Arg) {
532                let this = self;
533                newtype_ops__!(@helper::delegate   [&mut x.0]  [this] [0])
534                .$meth_assign(
535                newtype_ops__!(@helper::delegate [$($form2)*] [other] [0])
536                )
537            }
538        }
539    };
540
541    (@helper::delegate [&mut x.0] [$id:ident] [$fld:tt]) => { &mut $id.$fld };
542    (@helper::delegate     [&x.0] [$id:ident] [$fld:tt]) => {     &$id.$fld };
543    (@helper::delegate      [x.0] [$id:ident] [$fld:tt]) => {      $id.$fld };
544    (@helper::delegate        [x] [$id:ident] [$fld:tt]) => {           $id };
545}
546
547#[cfg(test)]
548mod tests {
549
550    // test:
551    //  * All possible impls for a primitive element
552    //  * A Cartesian product in many dimensions
553    //  * A type that is more than one token tree long (foo::Foo)
554    //  * Self types that do not derive Copy/Clone
555    mod broad_1 {
556        mod foo {
557            #[derive(Eq,PartialEq,Debug)]
558            pub struct Foo(pub i32);
559        }
560        #[derive(Eq,PartialEq,Debug)]
561        pub struct Bar(pub i32);
562
563        newtype_ops!{ {[foo::Foo][Bar]} integer {:=} {^&}Self {^&}{Self i32} }
564
565        use self::foo::Foo;
566        #[test]
567        fn test() {
568
569            // check that all desired impls work
570            assert_eq!(Foo(5), Foo(2) + Foo(3));
571            assert_eq!(Foo(5), Foo(2) + &Foo(3));
572            assert_eq!(Foo(5), &Foo(2) + Foo(3));
573            assert_eq!(Foo(5), &Foo(2) + &Foo(3));
574
575            assert_eq!(Foo(4), Foo(8) / 2);
576            assert_eq!(Foo(4), &Foo(8) / 2);
577            assert_eq!(Foo(4), Foo(8) / &2);
578            assert_eq!(Foo(4), &Foo(8) / &2);
579
580            assert_eq!(Foo(-3), -Foo(3));
581            assert_eq!(Foo(-3), -&Foo(3));
582
583            // check that Bar was not neglected
584            assert_eq!(Bar(5), Bar(2) + Bar(3));
585
586            let mut foo = Foo(4);
587            foo += 2;
588            assert_eq!(foo, Foo(6));
589            foo += Foo(2);
590            assert_eq!(foo, Foo(8));
591        }
592    }
593
594    // test:
595    //  * Element (not just Self) types that do not derive Copy/Clone
596    //  * That multiple layers of indirection are possible.
597    mod proper_forwarding {
598
599        #[derive(Eq,PartialEq,Debug)]
600        pub struct Inner(pub i32);
601        #[derive(Eq,PartialEq,Debug)]
602        pub struct Foo(pub Inner);
603
604        newtype_ops!{ [Inner] {add div neg} {assign normal} {^&}Self {^&}{Self i32}   }
605        newtype_ops!{ [Foo]   {add div neg} {assign normal} {^&}Self {^&}{Self Inner i32} }
606
607        #[test]
608        fn test() {
609            let foo = |x| Foo(Inner(x));
610
611            // check that all desired impls work
612            assert_eq!(foo(4), foo(8) / foo(2));
613            assert_eq!(foo(4), foo(8) / &foo(2));
614            assert_eq!(foo(4), &foo(8) / foo(2));
615            assert_eq!(foo(4), &foo(8) / &foo(2));
616
617            assert_eq!(foo(4), foo(8) / Inner(2));
618            assert_eq!(foo(4), &foo(8) / Inner(2));
619            assert_eq!(foo(4), foo(8) / &Inner(2));
620            assert_eq!(foo(4), &foo(8) / &Inner(2));
621
622            assert_eq!(foo(4), foo(8) / 2);
623            assert_eq!(foo(4), &foo(8) / 2);
624            assert_eq!(foo(4), foo(8) / &2);
625            assert_eq!(foo(4), &foo(8) / &2);
626
627            assert_eq!(foo(-3), -foo(3));
628            assert_eq!(foo(-3), -&foo(3));
629
630            let mut x = foo(4);
631            x += foo(2);
632            assert_eq!(x, foo(6));
633            x += Inner(2);
634            assert_eq!(x, foo(8));
635            x += 2;
636            assert_eq!(x, foo(10));
637        }
638    }
639
640    // test:
641    //  * that the right names link to the right operations
642    mod op_bindings {
643        // Make a separate struct for each operator to ensure that the right token
644        //  generates implementations for the right trait.
645        macro_rules! make_structs {
646            ($($T:ident),*) => {$(
647                #[derive(Eq,PartialEq,Debug,Copy,Clone)]
648                pub struct $T(pub i32);
649                impl From<i32> for $T {
650                    fn from(x: i32) -> $T { $T(x) }
651                }
652            )*};
653        }
654        // (each struct will be named after its std::ops trait)
655        make_structs!{ Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Neg, Not }
656
657        newtype_ops!{ [Add]    add    {assign normal} Self Self }
658        newtype_ops!{ [Sub]    sub    {assign normal} Self Self }
659        newtype_ops!{ [Mul]    mul    {assign normal} Self Self }
660        newtype_ops!{ [Div]    div    {assign normal} Self Self }
661        newtype_ops!{ [Rem]    rem    {assign normal} Self Self }
662        newtype_ops!{ [BitAnd] bitand {assign normal} Self Self }
663        newtype_ops!{ [BitOr]  bitor  {assign normal} Self Self }
664        newtype_ops!{ [BitXor] bitxor {assign normal} Self Self }
665        newtype_ops!{ [Neg]    neg    {assign normal} Self }
666        newtype_ops!{ [Not]    not    {assign normal} Self }
667
668        // Tests on operator output ensure the right methods of the underlying type are invoked.
669        fn run_binary_tests<T,F1,G1,F2,G2>(int_func: F1, foo_func: G1, int_eq: F2, foo_eq: G2)
670        where
671            T: ::core::fmt::Debug + From<i32> + Eq,
672            F1: Fn(i32, i32) -> i32, G1: Fn(T, T) -> T,
673            F2: Fn(&mut i32, i32),   G2: Fn(&mut T, T),
674        {
675            for a in 1..10 {
676                for b in 1..10 {
677                    let expected: T = int_func(a, b).into();
678                    let actual:   T = foo_func(a.into(), b.into());
679                    assert_eq!(actual, expected, "ouchie");
680
681                    let expected: T = { let mut x = a; int_eq(&mut x, b); x }.into();
682                    let actual:   T = { let mut x = a.into(); foo_eq(&mut x, b.into()); x };
683                    assert_eq!(actual, expected, "eihcuo");
684                }
685            }
686        }
687
688        fn run_unary_tests<T,F,G>(int_func: F, foo_func: G)
689        where T: ::core::fmt::Debug + From<i32> + Eq, F: Fn(i32) -> i32, G: Fn(T) -> T
690        {
691            for a in 1..10 {
692                let expected: T = int_func(a).into();
693                let actual:   T = foo_func(a.into());
694                assert_eq!(actual, expected, "ouchie");
695            }
696        }
697
698        #[test]
699        fn test() {
700            run_binary_tests::<Add   ,_,_,_,_>(|a,b| a + b, |a,b| a + b, |a,b| *a += b, |a,b| *a += b);
701            run_binary_tests::<Sub   ,_,_,_,_>(|a,b| a - b, |a,b| a - b, |a,b| *a -= b, |a,b| *a -= b);
702            run_binary_tests::<Mul   ,_,_,_,_>(|a,b| a * b, |a,b| a * b, |a,b| *a *= b, |a,b| *a *= b);
703            run_binary_tests::<Div   ,_,_,_,_>(|a,b| a / b, |a,b| a / b, |a,b| *a /= b, |a,b| *a /= b);
704            run_binary_tests::<Rem   ,_,_,_,_>(|a,b| a % b, |a,b| a % b, |a,b| *a %= b, |a,b| *a %= b);
705            run_binary_tests::<BitAnd,_,_,_,_>(|a,b| a & b, |a,b| a & b, |a,b| *a &= b, |a,b| *a &= b);
706            run_binary_tests::<BitOr ,_,_,_,_>(|a,b| a | b, |a,b| a | b, |a,b| *a |= b, |a,b| *a |= b);
707            run_binary_tests::<BitXor,_,_,_,_>(|a,b| a ^ b, |a,b| a ^ b, |a,b| *a ^= b, |a,b| *a ^= b);
708            run_unary_tests::<Neg,_,_>(|a| -a, |a| -a);
709            run_unary_tests::<Not,_,_>(|a| !a, |a| !a);
710        }
711
712        // ensure that the above tests are capable of failure.  (How meta.)
713        #[test] #[should_panic(expected = "ouchie")]
714        fn bad_binary() {
715            run_binary_tests::<Add   ,_,_,_,_>(|a,b| a * b, |a,b| a + b, |a,b| *a += b, |a,b| *a += b);
716        }
717
718        #[test] #[should_panic(expected = "eihcuo")]
719        fn bad_assign() {
720            run_binary_tests::<Add   ,_,_,_,_>(|a,b| a + b, |a,b| a + b, |a,b| *a *= b, |a,b| *a += b);
721        }
722
723        #[test] #[should_panic(expected = "ouchie")]
724        fn bad_unary() {
725            run_unary_tests::<Neg,_,_>(|a| !a, |a| -a);
726        }
727    }
728}