1#![cfg_attr(feature = "debug-trace-macros", feature(trace_macros))]
14#[cfg(feature = "debug-trace-macros")] trace_macros!(true);
15
16#[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 (@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 (@product::single($token:tt $($rest:tt)*) -> ($($args:tt)*)) => {
190 newtype_ops__!{ @product::next($($rest)*) -> ($($args)* $token) }};
191
192 (@product::unpack({$($token:tt)*} $($rest:tt)*) -> $args:tt) => {
196 newtype_ops__!{ @product::unpack_2({$($token)*} [$($rest)*]) -> $args }};
197 (@product::unpack_2({$($token:tt)*} $rest:tt) -> $args:tt) => {
199 $( newtype_ops__!{ @product::unpack_3($token $rest) -> $args } )* };
200 (@product::unpack_3($token:tt [$($rest:tt)*]) -> $args:tt) => {
204 newtype_ops__!{ @product::single($token $($rest)*) -> $args }};
205
206 (@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 (@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 (@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 (@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 (@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 (@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 (@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] [$arg $value_ty $recv_form] $traits $methods $recv_form $arg_form ) }
381 };
382
383 (@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 (@postprocess::blacklist([{kind:assign} {recv_form:[&x.0]} $arg_form:tt $arg:tt] $($rest:tt)*)) => { };
403 (@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 (@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 (@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 (@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 (@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} {tpars:$tpars:tt} {recv:$Recv:tt} {arg:$Arg:tt} {out:$Out:tt} )) => {
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 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 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 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 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 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 mod op_bindings {
641 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 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 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 #[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 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 #[cfg(nope)] #[test]
745 fn victim() {
746 let mut s = MyString("Hello world".to_string());
748 s += "!";
749 assert_eq!(s, MyString("Hello world!".to_string()));
750 }
751 }
752}