Skip to content

Commit eb0b4f7

Browse files
Improve Output explanation.
1 parent cbafcf2 commit eb0b4f7

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

book/src/04_traits/10_assoc_vs_generic.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ impl Add<u32> for u32 {
8181
type Output = u32;
8282

8383
fn add(self, rhs: u32) -> u32 {
84+
// ^^^
85+
// This could be written as `Self::Output` instead.
86+
// The compiler doesn't care, as long as the type you
87+
// specify here matches the type you assigned to `Output`
88+
// right above.
8489
// [...]
8590
}
8691
}
@@ -104,8 +109,31 @@ because `u32` implements `Add<&u32>` _as well as_ `Add<u32>`.
104109

105110
### `Output`
106111

107-
`Output`, on the other hand, **must** be uniquely determined once the types of the operands
108-
are known. That's why it's an associated type instead of a second generic parameter.
112+
`Output` represents the type of the result of the addition.
113+
114+
Why do we need `Output` in the first place? Can't we just use `Self` as output, the type implementing `Add`?
115+
We could, but it would limit the flexibility of the trait. In the standard library, for example, you'll find
116+
this implementation:
117+
118+
```rust
119+
impl Add<&u32> for &u32 {
120+
type Output = u32;
121+
122+
fn add(self, rhs: &u32) -> u32 {
123+
// [...]
124+
}
125+
}
126+
```
127+
128+
The type they're implementing the trait for is `&u32`, but the result of the addition is `u32`.
129+
It would be impossible[^flexible] to provide this implementation if `add` had to return `Self`, i.e. `&u32` in this case.
130+
`Output` lets `std` decouple the implementor from the return type, thus supporting this case.
131+
132+
On the other hand, `Output` can't be a generic parameter. The output type of the operation **must** be uniquely determined
133+
once the types of the operands are known. That's why it's an associated type: for a given combination of implementor
134+
and generic parameters, there is only one `Output` type.
135+
136+
## Conclusion
109137

110138
To recap:
111139

@@ -116,3 +144,8 @@ To recap:
116144
## References
117145

118146
- The exercise for this section is located in `exercises/04_traits/10_assoc_vs_generic`
147+
148+
[^flexible]: Flexibility is rarely free: the trait definition is more complex due to `Output`, and implementors have to reason about
149+
what they want to return. The trade-off is only justified if that flexibility is actually needed. Keep that in mind
150+
when designing your own traits.
151+

0 commit comments

Comments
 (0)