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