1 ## Traits: Defining Shared Behavior
3 A *trait* tells the Rust compiler about functionality a particular type has and
4 can share with other types. We can use traits to define shared behavior in an
5 abstract way. We can use trait bounds to specify that a generic can be any type
6 that has certain behavior.
8 > Note: Traits are similar to a feature often called *interfaces* in other
9 > languages, although with some differences.
13 A type’s behavior consists of the methods we can call on that type. Different
14 types share the same behavior if we can call the same methods on all of those
15 types. Trait definitions are a way to group method signatures together to
16 define a set of behaviors necessary to accomplish some purpose.
18 For example, let’s say we have multiple structs that hold various kinds and
19 amounts of text: a `NewsArticle` struct that holds a news story filed in a
20 particular location and a `Tweet` that can have at most 280 characters along
21 with metadata that indicates whether it was a new tweet, a retweet, or a reply
24 We want to make a media aggregator library that can display summaries of data
25 that might be stored in a `NewsArticle` or `Tweet` instance. To do this, we
26 need a summary from each type, and we need to request that summary by calling a
27 `summarize` method on an instance. Listing 10-12 shows the definition of a
28 `Summary` trait that expresses this behavior.
30 <span class="filename">Filename: src/lib.rs</span>
33 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/src/lib.rs}}
36 <span class="caption">Listing 10-12: A `Summary` trait that consists of the
37 behavior provided by a `summarize` method</span>
39 Here, we declare a trait using the `trait` keyword and then the trait’s name,
40 which is `Summary` in this case. Inside the curly brackets, we declare the
41 method signatures that describe the behaviors of the types that implement this
42 trait, which in this case is `fn summarize(&self) -> String`.
44 After the method signature, instead of providing an implementation within curly
45 brackets, we use a semicolon. Each type implementing this trait must provide
46 its own custom behavior for the body of the method. The compiler will enforce
47 that any type that has the `Summary` trait will have the method `summarize`
48 defined with this signature exactly.
50 A trait can have multiple methods in its body: the method signatures are listed
51 one per line and each line ends in a semicolon.
53 ### Implementing a Trait on a Type
55 Now that we’ve defined the desired behavior using the `Summary` trait, we can
56 implement it on the types in our media aggregator. Listing 10-13 shows an
57 implementation of the `Summary` trait on the `NewsArticle` struct that uses the
58 headline, the author, and the location to create the return value of
59 `summarize`. For the `Tweet` struct, we define `summarize` as the username
60 followed by the entire text of the tweet, assuming that tweet content is
61 already limited to 280 characters.
63 <span class="filename">Filename: src/lib.rs</span>
66 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/src/lib.rs:here}}
69 <span class="caption">Listing 10-13: Implementing the `Summary` trait on the
70 `NewsArticle` and `Tweet` types</span>
72 Implementing a trait on a type is similar to implementing regular methods. The
73 difference is that after `impl`, we put the trait name that we want to
74 implement, then use the `for` keyword, and then specify the name of the type we
75 want to implement the trait for. Within the `impl` block, we put the method
76 signatures that the trait definition has defined. Instead of adding a semicolon
77 after each signature, we use curly brackets and fill in the method body with
78 the specific behavior that we want the methods of the trait to have for the
81 After implementing the trait, we can call the methods on instances of
82 `NewsArticle` and `Tweet` in the same way we call regular methods, like this:
85 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs:here}}
88 This code prints `1 new tweet: horse_ebooks: of course, as you probably already
91 Note that because we defined the `Summary` trait and the `NewsArticle` and
92 `Tweet` types in the same *lib.rs* in Listing 10-13, they’re all in the same
93 scope. Let’s say this *lib.rs* is for a crate we’ve called `aggregator` and
94 someone else wants to use our crate’s functionality to implement the `Summary`
95 trait on a struct defined within their library’s scope. They would need to
96 bring the trait into their scope first. They would do so by specifying `use
97 aggregator::Summary;`, which then would enable them to implement `Summary` for
98 their type. The `Summary` trait would also need to be a public trait for
99 another crate to implement it, which it is because we put the `pub` keyword
100 before `trait` in Listing 10-12.
102 One restriction to note with trait implementations is that we can implement a
103 trait on a type only if either the trait or the type is local to our crate.
104 For example, we can implement standard library traits like `Display` on a
105 custom type like `Tweet` as part of our `aggregator` crate functionality,
106 because the type `Tweet` is local to our `aggregator` crate. We can also
107 implement `Summary` on `Vec<T>` in our `aggregator` crate, because the
108 trait `Summary` is local to our `aggregator` crate.
110 But we can’t implement external traits on external types. For example, we can’t
111 implement the `Display` trait on `Vec<T>` within our `aggregator` crate,
112 because `Display` and `Vec<T>` are defined in the standard library and aren’t
113 local to our `aggregator` crate. This restriction is part of a property of
114 programs called *coherence*, and more specifically the *orphan rule*, so named
115 because the parent type is not present. This rule ensures that other people’s
116 code can’t break your code and vice versa. Without the rule, two crates could
117 implement the same trait for the same type, and Rust wouldn’t know which
118 implementation to use.
120 ### Default Implementations
122 Sometimes it’s useful to have default behavior for some or all of the methods
123 in a trait instead of requiring implementations for all methods on every type.
124 Then, as we implement the trait on a particular type, we can keep or override
125 each method’s default behavior.
127 Listing 10-14 shows how to specify a default string for the `summarize` method
128 of the `Summary` trait instead of only defining the method signature, as we did
131 <span class="filename">Filename: src/lib.rs</span>
134 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/src/lib.rs:here}}
137 <span class="caption">Listing 10-14: Definition of a `Summary` trait with a
138 default implementation of the `summarize` method</span>
140 To use a default implementation to summarize instances of `NewsArticle` instead
141 of defining a custom implementation, we specify an empty `impl` block with
142 `impl Summary for NewsArticle {}`.
144 Even though we’re no longer defining the `summarize` method on `NewsArticle`
145 directly, we’ve provided a default implementation and specified that
146 `NewsArticle` implements the `Summary` trait. As a result, we can still call
147 the `summarize` method on an instance of `NewsArticle`, like this:
150 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs:here}}
153 This code prints `New article available! (Read more...)`.
155 Creating a default implementation for `summarize` doesn’t require us to change
156 anything about the implementation of `Summary` on `Tweet` in Listing 10-13. The
157 reason is that the syntax for overriding a default implementation is the same
158 as the syntax for implementing a trait method that doesn’t have a default
161 Default implementations can call other methods in the same trait, even if those
162 other methods don’t have a default implementation. In this way, a trait can
163 provide a lot of useful functionality and only require implementors to specify
164 a small part of it. For example, we could define the `Summary` trait to have a
165 `summarize_author` method whose implementation is required, and then define a
166 `summarize` method that has a default implementation that calls the
167 `summarize_author` method:
170 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:here}}
173 To use this version of `Summary`, we only need to define `summarize_author`
174 when we implement the trait on a type:
177 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:impl}}
180 After we define `summarize_author`, we can call `summarize` on instances of the
181 `Tweet` struct, and the default implementation of `summarize` will call the
182 definition of `summarize_author` that we’ve provided. Because we’ve implemented
183 `summarize_author`, the `Summary` trait has given us the behavior of the
184 `summarize` method without requiring us to write any more code.
187 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs:here}}
190 This code prints `1 new tweet: (Read more from @horse_ebooks...)`.
192 Note that it isn’t possible to call the default implementation from an
193 overriding implementation of that same method.
195 ### Traits as Parameters
197 Now that you know how to define and implement traits, we can explore how to use
198 traits to define functions that accept many different types.
200 For example, in Listing 10-13, we implemented the `Summary` trait on the
201 `NewsArticle` and `Tweet` types. We can define a `notify` function that calls
202 the `summarize` method on its `item` parameter, which is of some type that
203 implements the `Summary` trait. To do this, we can use the `impl Trait`
207 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/src/lib.rs:here}}
210 Instead of a concrete type for the `item` parameter, we specify the `impl`
211 keyword and the trait name. This parameter accepts any type that implements the
212 specified trait. In the body of `notify`, we can call any methods on `item`
213 that come from the `Summary` trait, such as `summarize`. We can call `notify`
214 and pass in any instance of `NewsArticle` or `Tweet`. Code that calls the
215 function with any other type, such as a `String` or an `i32`, won’t compile
216 because those types don’t implement `Summary`.
218 #### Trait Bound Syntax
220 The `impl Trait` syntax works for straightforward cases but is actually
221 syntax sugar for a longer form, which is called a *trait bound*; it looks like
225 pub fn notify<T: Summary>(item: &T) {
226 println!("Breaking news! {}", item.summarize());
230 This longer form is equivalent to the example in the previous section but is
231 more verbose. We place trait bounds with the declaration of the generic type
232 parameter after a colon and inside angle brackets.
234 The `impl Trait` syntax is convenient and makes for more concise code in simple
235 cases. The trait bound syntax can express more complexity in other cases. For
236 example, we can have two parameters that implement `Summary`. Using the `impl
237 Trait` syntax looks like this:
240 pub fn notify(item1: &impl Summary, item2: &impl Summary) {
243 If we wanted this function to allow `item1` and `item2` to have different
244 types, using `impl Trait` would be appropriate (as long as both types implement
245 `Summary`). If we wanted to force both parameters to have the same type, that’s
246 only possible to express using a trait bound, like this:
249 pub fn notify<T: Summary>(item1: &T, item2: &T) {
252 The generic type `T` specified as the type of the `item1` and `item2`
253 parameters constrains the function such that the concrete type of the value
254 passed as an argument for `item1` and `item2` must be the same.
256 #### Specifying Multiple Trait Bounds with the `+` Syntax
258 We can also specify more than one trait bound. Say we wanted `notify` to use
259 display formatting on `item` as well as the `summarize` method: we specify in
260 the `notify` definition that `item` must implement both `Display` and
261 `Summary`. We can do so using the `+` syntax:
264 pub fn notify(item: &(impl Summary + Display)) {
267 The `+` syntax is also valid with trait bounds on generic types:
270 pub fn notify<T: Summary + Display>(item: &T) {
273 With the two trait bounds specified, the body of `notify` can call `summarize`
274 and use `{}` to format `item`.
276 #### Clearer Trait Bounds with `where` Clauses
278 Using too many trait bounds has its downsides. Each generic has its own trait
279 bounds, so functions with multiple generic type parameters can contain lots of
280 trait bound information between the function’s name and its parameter list,
281 making the function signature hard to read. For this reason, Rust has alternate
282 syntax for specifying trait bounds inside a `where` clause after the function
283 signature. So instead of writing this:
286 fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
289 we can use a `where` clause, like this:
292 fn some_function<T, U>(t: &T, u: &U) -> i32
293 where T: Display + Clone,
298 This function’s signature is less cluttered: the function name, parameter list,
299 and return type are close together, similar to a function without lots of trait
302 ### Returning Types that Implement Traits
304 We can also use the `impl Trait` syntax in the return position to return a
305 value of some type that implements a trait, as shown here:
308 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/src/lib.rs:here}}
311 By using `impl Summary` for the return type, we specify that the
312 `returns_summarizable` function returns some type that implements the `Summary`
313 trait without naming the concrete type. In this case, `returns_summarizable`
314 returns a `Tweet`, but the code calling this function doesn’t know that.
316 The ability to return a type that is only specified by the trait it implements
317 is especially useful in the context of closures and iterators, which we cover
318 in Chapter 13. Closures and iterators create types that only the compiler knows
319 or types that are very long to specify. The `impl Trait` syntax lets you
320 concisely specify that a function returns some type that implements the
321 `Iterator` trait without needing to write out a very long type.
323 However, you can only use `impl Trait` if you’re returning a single type. For
324 example, this code that returns either a `NewsArticle` or a `Tweet` with the
325 return type specified as `impl Summary` wouldn’t work:
327 ```rust,ignore,does_not_compile
328 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/src/lib.rs:here}}
331 Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restrictions
332 around how the `impl Trait` syntax is implemented in the compiler. We’ll cover
333 how to write a function with this behavior in the [“Using Trait Objects That
334 Allow for Values of Different
335 Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
336 ignore --> section of Chapter 17.
338 ### Fixing the `largest` Function with Trait Bounds
340 Now that you know how to specify the behavior you want to use using the generic
341 type parameter’s bounds, let’s return to Listing 10-5 to fix the definition of
342 the `largest` function that uses a generic type parameter! Last time we tried
343 to run that code, we received this error:
346 {{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}}
349 In the body of `largest` we wanted to compare two values of type `T` using the
350 greater than (`>`) operator. Because that operator is defined as a default
351 method on the standard library trait `std::cmp::PartialOrd`, we need to specify
352 `PartialOrd` in the trait bounds for `T` so the `largest` function can work on
353 slices of any type that we can compare. We don’t need to bring `PartialOrd`
354 into scope because it’s in the prelude. Change the signature of `largest` to
358 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs:here}}
361 This time when we compile the code, we get a different set of errors:
364 {{#include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt}}
367 The key line in this error is `cannot move out of type [T], a non-copy slice`.
368 With our non-generic versions of the `largest` function, we were only trying to
369 find the largest `i32` or `char`. As discussed in the [“Stack-Only Data:
370 Copy”][stack-only-data-copy]<!-- ignore --> section in Chapter 4, types like
371 `i32` and `char` that have a known size can be stored on the stack, so they
372 implement the `Copy` trait. But when we made the `largest` function generic,
373 it became possible for the `list` parameter to have types in it that don’t
374 implement the `Copy` trait. Consequently, we wouldn’t be able to move the
375 value out of `list[0]` and into the `largest` variable, resulting in this
378 To call this code with only those types that implement the `Copy` trait, we can
379 add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of
380 a generic `largest` function that will compile as long as the types of the
381 values in the slice that we pass into the function implement the `PartialOrd`
382 *and* `Copy` traits, like `i32` and `char` do.
384 <span class="filename">Filename: src/main.rs</span>
387 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs}}
390 <span class="caption">Listing 10-15: A working definition of the `largest`
391 function that works on any generic type that implements the `PartialOrd` and
394 If we don’t want to restrict the `largest` function to the types that implement
395 the `Copy` trait, we could specify that `T` has the trait bound `Clone` instead
396 of `Copy`. Then we could clone each value in the slice when we want the
397 `largest` function to have ownership. Using the `clone` function means we’re
398 potentially making more heap allocations in the case of types that own heap
399 data like `String`, and heap allocations can be slow if we’re working with
400 large amounts of data.
402 Another way we could implement `largest` is for the function to return a
403 reference to a `T` value in the slice. If we change the return type to `&T`
404 instead of `T`, thereby changing the body of the function to return a
405 reference, we wouldn’t need the `Clone` or `Copy` trait bounds and we could
406 avoid heap allocations. Try implementing these alternate solutions on your own!
408 ### Using Trait Bounds to Conditionally Implement Methods
410 By using a trait bound with an `impl` block that uses generic type parameters,
411 we can implement methods conditionally for types that implement the specified
412 traits. For example, the type `Pair<T>` in Listing 10-16 always implements the
413 `new` function. But `Pair<T>` only implements the `cmp_display` method if its
414 inner type `T` implements the `PartialOrd` trait that enables comparison *and*
415 the `Display` trait that enables printing.
417 <span class="filename">Filename: src/lib.rs</span>
420 {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/lib.rs}}
423 <span class="caption">Listing 10-16: Conditionally implement methods on a
424 generic type depending on trait bounds</span>
426 We can also conditionally implement a trait for any type that implements
427 another trait. Implementations of a trait on any type that satisfies the trait
428 bounds are called *blanket implementations* and are extensively used in the
429 Rust standard library. For example, the standard library implements the
430 `ToString` trait on any type that implements the `Display` trait. The `impl`
431 block in the standard library looks similar to this code:
434 impl<T: Display> ToString for T {
439 Because the standard library has this blanket implementation, we can call the
440 `to_string` method defined by the `ToString` trait on any type that implements
441 the `Display` trait. For example, we can turn integers into their corresponding
442 `String` values like this because integers implement `Display`:
445 let s = 3.to_string();
448 Blanket implementations appear in the documentation for the trait in the
449 “Implementors” section.
451 Traits and trait bounds let us write code that uses generic type parameters to
452 reduce duplication but also specify to the compiler that we want the generic
453 type to have particular behavior. The compiler can then use the trait bound
454 information to check that all the concrete types used with our code provide the
455 correct behavior. In dynamically typed languages, we would get an error at
456 runtime if we called a method on a type which didn’t define the method. But Rust
457 moves these errors to compile time so we’re forced to fix the problems before
458 our code is even able to run. Additionally, we don’t have to write code that
459 checks for behavior at runtime because we’ve already checked at compile time.
460 Doing so improves performance without having to give up the flexibility of
463 Another kind of generic that we’ve already been using is called *lifetimes*.
464 Rather than ensuring that a type has the behavior we want, lifetimes ensure
465 that references are valid as long as we need them to be. Let’s look at how
468 [stack-only-data-copy]:
469 ch04-01-what-is-ownership.html#stack-only-data-copy
470 [using-trait-objects-that-allow-for-values-of-different-types]:
471 ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types