diff --git a/src/lib.rs b/src/lib.rs index 207602b..0e0ae3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -696,6 +696,26 @@ pub fn num(input: TokenStream) -> TokenStream { import.wrap(impl_).into() } +/// Derives [`core::ops::Neg`][neg] for newtypes. The inner type must already implement `Neg`. +/// +/// [neg]: https://doc.rust-lang.org/stable/core/ops/trait.Neg.html +#[proc_macro_derive(Neg, attributes(num_traits))] +pub fn neg(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + let impl_ = quote! { + impl ::core::ops::Neg for #name { + type Output = Self; + #[inline] + fn neg(self) -> Self { + #name(<#inner_ty as ::core::ops::Neg>::neg(self.0)) + } + } + }; + impl_.into() +} + /// Derives [`num_traits::Float`][float] for newtypes. The inner type must already implement /// `Float`. /// diff --git a/tests/newtype.rs b/tests/newtype.rs index 71b06b3..1391a6e 100644 --- a/tests/newtype.rs +++ b/tests/newtype.rs @@ -31,18 +31,12 @@ fn test_derive_unsigned_works() { One, Zero, Num, + Neg, Float, Signed, )] struct MyFloat(f64); -impl Neg for MyFloat { - type Output = MyFloat; - fn neg(self) -> Self { - MyFloat(self.0.neg()) - } -} - #[test] fn test_from_primitive() { assert_eq!(MyFloat::from_u32(25), Some(MyFloat(25.0))); @@ -97,6 +91,11 @@ fn test_num() { assert_eq!(MyFloat::from_str_radix("25", 10).ok(), Some(MyFloat(25.0))); } +#[test] +fn test_neg() { + assert_eq!(MyFloat(4.0).neg(), MyFloat(-4.0)); +} + #[test] fn test_float() { assert_eq!(MyFloat(4.0).log(MyFloat(2.0)), MyFloat(2.0));