1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
# What `#[derive(Add)]` generates
The derived `Add` implementation will allow two structs of the same type to be
added together. This is done by adding their respective fields together and
creating a new struct with those values.
For enums each variant can be added in a similar way to another instance of that
same variant. There's one big difference however: it returns a
`Result<EnumType>`, because an error is returned when two different variants are
added together.
## Tuple structs
When deriving `Add` for a tuple struct with two fields like this:
```rust
# use derive_more::Add;
#
#[derive(Add)]
struct MyInts(i32, i32);
```
Code like this will be generated:
```rust
# struct MyInts(i32, i32);
impl derive_more::Add for MyInts {
type Output = MyInts;
fn add(self, rhs: MyInts) -> MyInts {
MyInts(self.0.add(rhs.0), self.1.add(rhs.1))
}
}
```
The behaviour is similar with more or less fields.
## Regular structs
When deriving `Add` for a regular struct with two fields like this:
```rust
# use derive_more::Add;
#
#[derive(Add)]
struct Point2D {
x: i32,
y: i32,
}
```
Code like this will be generated:
```rust
# struct Point2D {
# x: i32,
# y: i32,
# }
impl derive_more::Add for Point2D {
type Output = Point2D;
fn add(self, rhs: Point2D) -> Point2D {
Point2D {
x: self.x.add(rhs.x),
y: self.y.add(rhs.y),
}
}
}
```
The behaviour is similar for more or less fields.
## Enums
There's a big difference between the code that is generated for the two struct
types and the one that is generated for enums. The code for enums returns
`Result<EnumType>` instead of an `EnumType` itself. This is because adding an
enum to another enum is only possible if both are the same variant. This makes
the generated code much more complex as well, because this check needs to be
done. For instance when deriving `Add` for an enum like this:
```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,
}
```
Code like this will be generated:
```rust
# enum MixedInts {
# SmallInt(i32),
# BigInt(i64),
# TwoSmallInts(i32, i32),
# NamedSmallInts { x: i32, y: i32 },
# UnsignedOne(u32),
# UnsignedTwo(u32),
# Unit,
# }
impl derive_more::Add for MixedInts {
type Output = Result<MixedInts, derive_more::BinaryError>;
fn add(self, rhs: MixedInts) -> Result<MixedInts, derive_more::BinaryError> {
match (self, rhs) {
(MixedInts::SmallInt(__l_0), MixedInts::SmallInt(__r_0)) => {
Ok(MixedInts::SmallInt(__l_0.add(__r_0)))
}
(MixedInts::BigInt(__l_0), MixedInts::BigInt(__r_0)) => {
Ok(MixedInts::BigInt(__l_0.add(__r_0)))
}
(MixedInts::TwoSmallInts(__l_0, __l_1), MixedInts::TwoSmallInts(__r_0, __r_1)) => {
Ok(MixedInts::TwoSmallInts(__l_0.add(__r_0), __l_1.add(__r_1)))
}
(MixedInts::NamedSmallInts { x: __l_0, y: __l_1 },
MixedInts::NamedSmallInts { x: __r_0, y: __r_1 }) => {
Ok(MixedInts::NamedSmallInts {
x: __l_0.add(__r_0),
y: __l_1.add(__r_1),
})
}
(MixedInts::UnsignedOne(__l_0), MixedInts::UnsignedOne(__r_0)) => {
Ok(MixedInts::UnsignedOne(__l_0.add(__r_0)))
}
(MixedInts::UnsignedTwo(__l_0), MixedInts::UnsignedTwo(__r_0)) => {
Ok(MixedInts::UnsignedTwo(__l_0.add(__r_0)))
}
(MixedInts::Unit, MixedInts::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 type that throws an error when adding it to itself.
|