# What `#[derive(Add)]` generates > **NOTE**: `Sub`, `BitAnd`, `BitOr` and `BitXor` derives are fully equivalent > to the `Add` derive described below. Deriving `Add` works by adding two values structurally (field by field, according to their type structure). ## Structs The derived `Add` implementation will allow two structs of the same type to be added together. This is done by `Add`ing their respective fields together and creating a new struct with those values. ```rust # use derive_more::Add; # #[derive(Add)] struct MyInts(i32, i32); #[derive(Add)] struct Point2D { x: i32, y: i32, } ``` This generates code equivalent to: ```rust # use std::ops::Add; # # struct MyInts(i32, i32); # # struct Point2D { # x: i32, # y: i32, # } # impl Add for MyInts { type Output = Self; fn add(self, rhs: Self) -> Self::Output { match (self, rhs) { (Self(self_0, self_1), Self(rhs_0, rhs_1)) => { Self(Add::add(self_0, rhs_0), Add::add(self_1, rhs_1)) } } } } impl Add for Point2D { type Output = Self; fn add(self, rhs: Self) -> Self::Output { match (self, rhs) { (Self { x: self_0, y: self_1 }, Self { x: rhs_0, y: rhs_1 }) => { Self { x: Add::add(self_0, rhs_0), y: Add::add(self_1, rhs_1) } } } } } ``` The behaviour is similar with more or less fields. ### Ignoring Sometimes a struct needs to hold a field (most commonly `PhantomData`) that doesn't participate in `Add` implementation. Such field could be ignored using the `#[add(skip)]` attribute. ```rust # use core::marker::PhantomData; # use derive_more::Add; # #[derive(Add)] struct TupleWithZst(i32, #[add(skip)] PhantomData); #[derive(Add)] struct StructWithZst { x: i32, #[add(skip)] // or #[add(ignore)] _marker: PhantomData, } ``` ## Enums For enums each variant can be `Add`ed in a similar way to another instance of the same variant. There's one big difference however: it returns a `Result`, because an error is returned when two different variants are `Add`ed together. ```rust # use derive_more::Add; # #[derive(Add)] enum MixedInts { SmallInt(i32), BigInt(i64), TwoSmallInts(i32, i32), NamedSmallInts { x: i32, y: i32 }, UnsignedOne(u32), UnsignedTwo(u32), Unit, } ``` This generates code equivalent to: ```rust # use std::ops::Add; # # enum MixedInts { # SmallInt(i32), # BigInt(i64), # TwoSmallInts(i32, i32), # NamedSmallInts { x: i32, y: i32 }, # UnsignedOne(u32), # UnsignedTwo(u32), # Unit, # } # impl Add for MixedInts { type Output = Result; fn add(self, rhs: Self) -> Self::Output { match (self, rhs) { (Self::SmallInt(self_0), Self::SmallInt(rhs_0)) => { Ok(Self::SmallInt(Add::add(self_0, rhs_0))) } (Self::BigInt(self_0), Self::BigInt(rhs_0)) => { Ok(Self::BigInt(Add::add(self_0, rhs_0))) } (Self::TwoSmallInts(self_0, self_1), Self::TwoSmallInts(rhs_0, rhs_1)) => { Ok(Self::TwoSmallInts(Add::add(self_0, rhs_0), Add::add(self_1, rhs_1))) } (Self::NamedSmallInts { x: self_0, y: self_1 }, Self::NamedSmallInts { x: rhs_0, y: rhs_1 }) => { Ok(Self::NamedSmallInts { x: Add::add(self_0, rhs_0), y: Add::add(self_1, rhs_1), }) } (Self::UnsignedOne(self_0), Self::UnsignedOne(rhs_0)) => { Ok(Self::UnsignedOne(Add::add(self_0, rhs_0))) } (Self::UnsignedTwo(self_0), Self::UnsignedTwo(rhs_0)) => { Ok(Self::UnsignedTwo(Add::add(self_0, rhs_0))) } (Self::Unit, Self::Unit) => Err(derive_more::BinaryError::Unit( derive_more::UnitError::new("add"), )), _ => Err(derive_more::BinaryError::Mismatch( derive_more::WrongVariantError::new("add"), )), } } } ``` Also note the `Unit` variant that throws a `derive_more::UnitError` when `Add`ing it to itself. ### Ignoring Similarly to structs, enum fields could be ignored using the `#[add(skip)]` attribute. ```rust # use derive_more::Add; # struct I32(i32); // doesn't implement `Add` #[derive(Add)] enum MixedInts { TwoSmallInts(i32, #[add(skip)] I32), NamedSmallInts { #[add(skip)] // or #[add(ignore)] x: I32, y: i32, }, } ``` > **NOTE**: Ignoring all the fields of a variant or ignoring the variant itself is not allowed > (results in a compilation error).