Skip to content

Commit 0e92165

Browse files
committed
Show impl<T>
This includes a new example with Rectangle, instead of reusing HasArea, because fn area would require the Mul trait, and the added complexity of that would be better left for the Operators and Overloading chapter. Squashed at reviewer's request: Move teaser for trait bounds to bottom
1 parent 04badd6 commit 0e92165

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

src/doc/trpl/generics.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ fn takes_two_things<T, U>(x: T, y: U) {
101101
}
102102
```
103103

104-
Generic functions are most useful with ‘trait bounds’, which we’ll cover in the
105-
[section on traits][traits].
106-
107-
[traits]: traits.html
108-
109104
## Generic structs
110105

111106
You can store a generic type in a `struct` as well:
@@ -122,3 +117,28 @@ let float_origin = Point { x: 0.0, y: 0.0 };
122117

123118
Similarly to functions, the `<T>` is where we declare the generic parameters,
124119
and we then use `x: T` in the type declaration, too.
120+
121+
When you want to add an implementation for the generic struct, you just
122+
declare the type parameter after the `impl`:
123+
124+
```rust
125+
# struct Point<T> {
126+
# x: T,
127+
# y: T,
128+
# }
129+
#
130+
impl<T> Point<T> {
131+
fn swap(&mut self) {
132+
std::mem::swap(&mut self.x, &mut self.y);
133+
}
134+
}
135+
```
136+
137+
So far you’ve seen generics that take absolutely any type. These are useful in
138+
many cases: you’ve already seen `Option<T>`, and later you’ll meet universal
139+
container types like [`Vec<T>`][Vec]. On the other hand, often you want to
140+
trade that flexibility for increased expressive power. Read about [trait
141+
bounds][traits] to see why and how.
142+
143+
[traits]: traits.html
144+
[Vec]: ../std/vec/struct.Vec.html

src/doc/trpl/traits.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,57 @@ We get a compile-time error:
152152
error: the trait `HasArea` is not implemented for the type `_` [E0277]
153153
```
154154

155+
## Traits bounds for generic structs
156+
157+
Trait constraints also can apply to implementations for generic structs. Just
158+
append the constraint when you declare type parameters. Here is a new type
159+
type `Rectangle<T>` and its operation `is_square()`:
160+
161+
```rust
162+
struct Rectangle<T> {
163+
x: T,
164+
y: T,
165+
width: T,
166+
height: T,
167+
}
168+
169+
impl<T: PartialEq> Rectangle<T> {
170+
fn is_square(&self) -> bool {
171+
self.width == self.height
172+
}
173+
}
174+
175+
fn main() {
176+
let mut r = Rectangle {
177+
x: 0,
178+
y: 0,
179+
width: 47,
180+
height: 47,
181+
};
182+
183+
assert!(r.is_square());
184+
185+
r.height = 42;
186+
assert!(!r.is_square());
187+
}
188+
```
189+
190+
`is_square()` needs to check that the sides are equal, so the sides must be of
191+
a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
192+
193+
```ignore
194+
impl<T: PartialEq> Rectangle<T> { ... }
195+
```
196+
197+
Now, a rectangle can be defined in terms of any type that can be compared for
198+
equality.
199+
200+
[PartialEq]: ../core/cmp/trait.PartialEq.html
201+
202+
203+
204+
# Rules for implementing traits
205+
155206
So far, we’ve only added trait implementations to structs, but you can
156207
implement a trait for any type. So technically, we _could_ implement `HasArea`
157208
for `i32`:

0 commit comments

Comments
 (0)