@@ -447,3 +447,52 @@ pub fn to_primitive(input: TokenStream) -> TokenStream {
447447
448448 dummy_const_trick ( "ToPrimitive" , & name, impl_) . into ( )
449449}
450+
451+ const NEWTYPE_ONLY : & ' static str = "This trait can only be derived for newtypes" ;
452+
453+ /// Derives [`num_traits::NumOps`][num_ops] for newtypes. The inner type must already implement
454+ /// `NumOps`.
455+ ///
456+ /// [num_ops]: https://docs.rs/num-traits/0.2/num_traits/trait.NumOps.html
457+ ///
458+ /// Note that, since `NumOps` is really a trait alias for `Add + Sub + Mul + Div + Rem`, this macro
459+ /// generates impls for _those_ traits. Furthermore, in all generated impls, `RHS=Self` and
460+ /// `Output=Self`.
461+ #[ proc_macro_derive( NumOps ) ]
462+ pub fn num_ops ( input : TokenStream ) -> TokenStream {
463+ let ast: syn:: DeriveInput = syn:: parse ( input) . unwrap ( ) ;
464+ let name = & ast. ident ;
465+ let inner_ty = newtype_inner ( & ast. data ) . expect ( NEWTYPE_ONLY ) ;
466+ dummy_const_trick ( "NumOps" , & name, quote ! {
467+ impl :: std:: ops:: Add for #name {
468+ type Output = Self ;
469+ fn add( self , other: Self ) -> Self {
470+ #name( <#inner_ty as :: std:: ops:: Add >:: add( self . 0 , other. 0 ) )
471+ }
472+ }
473+ impl :: std:: ops:: Sub for #name {
474+ type Output = Self ;
475+ fn sub( self , other: Self ) -> Self {
476+ #name( <#inner_ty as :: std:: ops:: Sub >:: sub( self . 0 , other. 0 ) )
477+ }
478+ }
479+ impl :: std:: ops:: Mul for #name {
480+ type Output = Self ;
481+ fn mul( self , other: Self ) -> Self {
482+ #name( <#inner_ty as :: std:: ops:: Mul >:: mul( self . 0 , other. 0 ) )
483+ }
484+ }
485+ impl :: std:: ops:: Div for #name {
486+ type Output = Self ;
487+ fn div( self , other: Self ) -> Self {
488+ #name( <#inner_ty as :: std:: ops:: Div >:: div( self . 0 , other. 0 ) )
489+ }
490+ }
491+ impl :: std:: ops:: Rem for #name {
492+ type Output = Self ;
493+ fn rem( self , other: Self ) -> Self {
494+ #name( <#inner_ty as :: std:: ops:: Rem >:: rem( self . 0 , other. 0 ) )
495+ }
496+ }
497+ } ) . into ( )
498+ }
0 commit comments