11# What ` #[derive(Add)] ` generates
22
3- The derived ` Add ` implementation will allow two structs of the same type to be
4- added together. This is done by adding their respective fields together and
5- creating a new struct with those values.
6- For enums each variant can be added in a similar way to another instance of that
7- same variant. There's one big difference however: it returns a
8- ` Result<EnumType> ` , because an error is returned when two different variants are
9- added together.
3+ > ** NOTE** : ` Sub ` , ` BitAnd ` , ` BitOr ` and ` BitXor ` derives are fully equivalent
4+ > to the ` Add ` derive described below.
5+
6+ Deriving ` Add ` works by adding two values structurally (field by field, according
7+ to their type structure).
108
119
1210
1311
14- ## Tuple structs
12+ ## Structs
1513
16- When deriving ` Add ` for a tuple struct with two fields like this:
14+ The derived ` Add ` implementation will allow two structs of the same type to be
15+ added together. This is done by ` Add ` ing their respective fields together and
16+ creating a new struct with those values.
1717
1818``` rust
1919# use derive_more :: Add ;
2020#
2121#[derive(Add )]
2222struct MyInts (i32 , i32 );
23- ```
24-
25- Code like this will be generated:
2623
24+ #[derive(Add )]
25+ struct Point2D {
26+ x : i32 ,
27+ y : i32 ,
28+ }
29+ ```
30+ This generates code equivalent to:
2731``` rust
32+ # use std :: ops :: Add ;
33+ #
2834# struct MyInts (i32 , i32 );
29- impl derive_more :: core :: ops :: Add for MyInts {
30- type Output = MyInts ;
31- fn add (self , rhs : MyInts ) -> MyInts {
32- MyInts (self . 0. add (rhs . 0 ), self . 1. add (rhs . 1 ))
35+ #
36+ # struct Point2D {
37+ # x : i32 ,
38+ # y : i32 ,
39+ # }
40+ #
41+ impl Add for MyInts {
42+ type Output = Self ;
43+
44+ fn add (self , rhs : Self ) -> Self :: Output {
45+ match (self , rhs ) {
46+ (Self (self_0 , self_1 ), Self (rhs_0 , rhs_1 )) => {
47+ Self (Add :: add (self_0 , rhs_0 ), Add :: add (self_1 , rhs_1 ))
48+ }
49+ }
3350 }
3451}
35- ```
3652
37- The behaviour is similar with more or less fields.
53+ impl Add for Point2D {
54+ type Output = Self ;
3855
56+ fn add (self , rhs : Self ) -> Self :: Output {
57+ match (self , rhs ) {
58+ (Self { x : self_0 , y : self_1 }, Self { x : rhs_0 , y : rhs_1 }) => {
59+ Self { x : Add :: add (self_0 , rhs_0 ), y : Add :: add (self_1 , rhs_1 ) }
60+ }
61+ }
62+ }
63+ }
64+ ```
3965
66+ The behaviour is similar with more or less fields.
4067
4168
42- ## Regular structs
69+ ### Ignoring
4370
44- When deriving ` Add ` for a regular struct with two fields like this:
71+ Sometimes a struct needs to hold a field (most commonly ` PhantomData ` ) that doesn't
72+ participate in ` Add ` implementation. Such field could be ignored using the ` #[add(skip)] `
73+ attribute.
4574
4675``` rust
76+ # use core :: marker :: PhantomData ;
4777# use derive_more :: Add ;
4878#
4979#[derive(Add )]
50- struct Point2D {
51- x : i32 ,
52- y : i32 ,
53- }
54- ```
55-
56- Code like this will be generated:
80+ struct TupleWithZst <T >(i32 , #[add(skip)] PhantomData <T >);
5781
58- ``` rust
59- # struct Point2D {
60- # x : i32 ,
61- # y : i32 ,
62- # }
63- impl derive_more :: core :: ops :: Add for Point2D {
64- type Output = Point2D ;
65- fn add (self , rhs : Point2D ) -> Point2D {
66- Point2D {
67- x : self . x. add (rhs . x),
68- y : self . y. add (rhs . y),
69- }
70- }
82+ #[derive(Add )]
83+ struct StructWithZst <T > {
84+ x : i32 ,
85+ #[add(skip)] // or #[add(ignore)]
86+ _marker : PhantomData <T >,
7187}
7288```
7389
74- The behaviour is similar for more or less fields.
75-
7690
7791
7892
7993## Enums
8094
81- There's a big difference between the code that is generated for the two struct
82- types and the one that is generated for enums. The code for enums returns
83- ` Result<EnumType> ` instead of an ` EnumType ` itself. This is because adding an
84- enum to another enum is only possible if both are the same variant. This makes
85- the generated code much more complex as well, because this check needs to be
86- done. For instance when deriving ` Add ` for an enum like this:
95+ For enums each variant can be ` Add ` ed in a similar way to another instance of the
96+ same variant. There's one big difference however: it returns a ` Result<EnumType> ` ,
97+ because an error is returned when two different variants are ` Add ` ed together.
8798
8899``` rust
89100# use derive_more :: Add ;
@@ -99,10 +110,10 @@ enum MixedInts {
99110 Unit ,
100111}
101112```
102-
103- Code like this will be generated:
104-
113+ This generates code equivalent to:
105114``` rust
115+ # use std :: ops :: Add ;
116+ #
106117# enum MixedInts {
107118# SmallInt (i32 ),
108119# BigInt (i64 ),
@@ -112,33 +123,35 @@ Code like this will be generated:
112123# UnsignedTwo (u32 ),
113124# Unit ,
114125# }
115- impl derive_more :: core :: ops :: Add for MixedInts {
116- type Output = Result <MixedInts , derive_more :: BinaryError >;
117- fn add (self , rhs : MixedInts ) -> Result <MixedInts , derive_more :: BinaryError > {
126+ #
127+ impl Add for MixedInts {
128+ type Output = Result <Self , derive_more :: BinaryError >;
129+
130+ fn add (self , rhs : Self ) -> Self :: Output {
118131 match (self , rhs ) {
119- (MixedInts :: SmallInt (__l_0 ), MixedInts :: SmallInt (__r_0 )) => {
120- Ok (MixedInts :: SmallInt (__l_0 . add (__r_0 )))
132+ (Self :: SmallInt (self_0 ), Self :: SmallInt (rhs_0 )) => {
133+ Ok (Self :: SmallInt (Add :: add (self_0 , rhs_0 )))
121134 }
122- (MixedInts :: BigInt (__l_0 ), MixedInts :: BigInt (__r_0 )) => {
123- Ok (MixedInts :: BigInt (__l_0 . add (__r_0 )))
135+ (Self :: BigInt (self_0 ), Self :: BigInt (rhs_0 )) => {
136+ Ok (Self :: BigInt (Add :: add (self_0 , rhs_0 )))
124137 }
125- (MixedInts :: TwoSmallInts (__l_0 , __l_1 ), MixedInts :: TwoSmallInts (__r_0 , __r_1 )) => {
126- Ok (MixedInts :: TwoSmallInts (__l_0 . add (__r_0 ), __l_1 . add (__r_1 )))
138+ (Self :: TwoSmallInts (self_0 , self_1 ), Self :: TwoSmallInts (rhs_0 , rhs_1 )) => {
139+ Ok (Self :: TwoSmallInts (Add :: add (self_0 , rhs_0 ), Add :: add (self_1 , rhs_1 )))
127140 }
128- (MixedInts :: NamedSmallInts { x : __l_0 , y : __l_1 },
129- MixedInts :: NamedSmallInts { x : __r_0 , y : __r_1 }) => {
130- Ok (MixedInts :: NamedSmallInts {
131- x : __l_0 . add (__r_0 ),
132- y : __l_1 . add (__r_1 ),
141+ (Self :: NamedSmallInts { x : self_0 , y : self_1 },
142+ Self :: NamedSmallInts { x : rhs_0 , y : rhs_1 }) => {
143+ Ok (Self :: NamedSmallInts {
144+ x : Add :: add (self_0 , rhs_0 ),
145+ y : Add :: add (self_1 , rhs_1 ),
133146 })
134147 }
135- (MixedInts :: UnsignedOne (__l_0 ), MixedInts :: UnsignedOne (__r_0 )) => {
136- Ok (MixedInts :: UnsignedOne (__l_0 . add (__r_0 )))
148+ (Self :: UnsignedOne (self_0 ), Self :: UnsignedOne (rhs_0 )) => {
149+ Ok (Self :: UnsignedOne (Add :: add (self_0 , rhs_0 )))
137150 }
138- (MixedInts :: UnsignedTwo (__l_0 ), MixedInts :: UnsignedTwo (__r_0 )) => {
139- Ok (MixedInts :: UnsignedTwo (__l_0 . add (__r_0 )))
151+ (Self :: UnsignedTwo (self_0 ), Self :: UnsignedTwo (rhs_0 )) => {
152+ Ok (Self :: UnsignedTwo (Add :: add (self_0 , rhs_0 )))
140153 }
141- (MixedInts :: Unit , MixedInts :: Unit ) => Err (derive_more :: BinaryError :: Unit (
154+ (Self :: Unit , Self :: Unit ) => Err (derive_more :: BinaryError :: Unit (
142155 derive_more :: UnitError :: new (" add" ),
143156 )),
144157 _ => Err (derive_more :: BinaryError :: Mismatch (
@@ -149,4 +162,28 @@ impl derive_more::core::ops::Add for MixedInts {
149162}
150163```
151164
152- Also note the Unit type that throws an error when adding it to itself.
165+ Also note the ` Unit ` variant that throws a ` derive_more::UnitError ` when ` Add ` ing it to itself.
166+
167+
168+ ### Ignoring
169+
170+ Similarly to structs, enum fields could be ignored using the ` #[add(skip)] ` attribute.
171+
172+ ``` rust
173+ # use derive_more :: Add ;
174+ #
175+ struct I32 (i32 ); // doesn't implement `Add`
176+
177+ #[derive(Add )]
178+ enum MixedInts {
179+ TwoSmallInts (i32 , #[add(skip)] I32 ),
180+ NamedSmallInts {
181+ #[add(skip)] // or #[add(ignore)]
182+ x : I32 ,
183+ y : i32 ,
184+ },
185+ }
186+ ```
187+
188+ > ** NOTE** : Ignoring all the fields of a variant or ignoring the variant itself is not allowed
189+ > (results in a compilation error).
0 commit comments