]> git.proxmox.com Git - rustc.git/blob - src/doc/book/second-edition/nostarch/chapter10.md
New upstream version 1.21.0+dfsg1
[rustc.git] / src / doc / book / second-edition / nostarch / chapter10.md
1
2 [TOC]
3
4 # Generic Types, Traits, and Lifetimes
5
6 Every programming language has tools to deal effectively with duplication of
7 concepts; in Rust, one of those tools is *generics*. Generics are abstract
8 stand-ins for concrete types or other properties. We can express properties of
9 generics, such as their behavior or how they relate to other generics, without
10 needing to know when we’re writing and compiling the code what will actually be
11 in their place.
12
13 In the same way that a function takes parameters whose value we don’t know in
14 order to write code once that will be run on multiple concrete values, we can
15 write functions that take parameters of some generic type instead of a concrete
16 type like `i32` or `String`. We’ve already used generics in Chapter 6 with
17 `Option<T>`, Chapter 8 with `Vec<T>` and `HashMap<K, V>`, and Chapter 9 with
18 `Result<T, E>`. In this chapter, we’ll explore how to define our own types,
19 functions, and methods with generics!
20
21 First, we’re going to review the mechanics of extracting a function that
22 reduces code duplication. Then we’ll use the same mechanics to make a generic
23 function out of two functions that only differ in the types of their
24 parameters. We’ll go over using generic types in struct and enum definitions
25 too.
26
27 After that, we’ll discuss *traits*, which are a way to define behavior in a
28 generic way. Traits can be combined with generic types in order to constrain a
29 generic type to those types that have a particular behavior, rather than any
30 type at all.
31
32 Finally, we’ll discuss *lifetimes*, which are a kind of generic that let us
33 give the compiler information about how references are related to each other.
34 Lifetimes are the feature in Rust that allow us to borrow values in many
35 situations and still have the compiler check that references will be valid.
36
37 ## Removing Duplication by Extracting a Function
38
39 Before getting into generics syntax, let’s first review a technique for dealing
40 with duplication that doesn’t use generic types: extracting a function. Once
41 that’s fresh in our minds, we’ll use the same mechanics with generics to
42 extract a generic function! In the same way that you recognize duplicated code
43 to extract into a function, you’ll start to recognize duplicated code that can
44 use generics.
45
46 Consider a small program that finds the largest number in a list, shown in
47 Listing 10-1:
48
49 Filename: src/main.rs
50
51 ```
52 fn main() {
53 let numbers = vec![34, 50, 25, 100, 65];
54
55 let mut largest = numbers[0];
56
57 for number in numbers {
58 if number > largest {
59 largest = number;
60 }
61 }
62
63 println!("The largest number is {}", largest);
64 }
65 ```
66
67 Listing 10-1: Code to find the largest number in a list of numbers
68
69 This code takes a list of integers, stored here in the variable `numbers`. It
70 puts the first item in the list in a variable named `largest`. Then it iterates
71 through all the numbers in the list, and if the current value is greater than
72 the number stored in `largest`, it replaces the value in `largest`. If the
73 current value is smaller than the largest value seen so far, `largest` is not
74 changed. When all the items in the list have been considered, `largest` will
75 hold the largest value, which in this case is 100.
76
77 If we needed to find the largest number in two different lists of numbers, we
78 could duplicate the code in Listing 10-1 and have the same logic exist in two
79 places in the program, as in Listing 10-2:
80
81 Filename: src/main.rs
82
83 ```
84 fn main() {
85 let numbers = vec![34, 50, 25, 100, 65];
86
87 let mut largest = numbers[0];
88
89 for number in numbers {
90 if number > largest {
91 largest = number;
92 }
93 }
94
95 println!("The largest number is {}", largest);
96
97 let numbers = vec![102, 34, 6000, 89, 54, 2, 43, 8];
98
99 let mut largest = numbers[0];
100
101 for number in numbers {
102 if number > largest {
103 largest = number;
104 }
105 }
106
107 println!("The largest number is {}", largest);
108 }
109 ```
110
111 Listing 10-2: Code to find the largest number in *two* lists of numbers
112
113 While this code works, duplicating code is tedious and error-prone, and means
114 we have multiple places to update the logic if we need to change it.
115
116 <!-- Are we safe assuming the reader will be familiar with the term
117 "abstraction" in this context, or do we want to give a brief definition? -->
118 <!-- Yes, our audience will be familiar with this term. /Carol -->
119
120 To eliminate this duplication, we can create an abstraction, which in this case
121 will be in the form of a function that operates on any list of integers given
122 to the function in a parameter. This will increase the clarity of our code and
123 let us communicate and reason about the concept of finding the largest number
124 in a list independently of the specific places this concept is used.
125
126 In the program in Listing 10-3, we’ve extracted the code that finds the largest
127 number into a function named `largest`. This program can find the largest
128 number in two different lists of numbers, but the code from Listing 10-1 only
129 exists in one spot:
130
131 Filename: src/main.rs
132
133 ```
134 fn largest(list: &[i32]) -> i32 {
135 let mut largest = list[0];
136
137 for &item in list.iter() {
138 if item > largest {
139 largest = item;
140 }
141 }
142
143 largest
144 }
145
146 fn main() {
147 let numbers = vec![34, 50, 25, 100, 65];
148
149 let result = largest(&numbers);
150 println!("The largest number is {}", result);
151
152 let numbers = vec![102, 34, 6000, 89, 54, 2, 43, 8];
153
154 let result = largest(&numbers);
155 println!("The largest number is {}", result);
156 }
157 ```
158
159 Listing 10-3: Abstracted code to find the largest number in two lists
160
161 The function has a parameter, `list`, which represents any concrete slice of
162 `i32` values that we might pass into the function. The code in the function
163 definition operates on the `list` representation of any `&[i32]`. When we call
164 the `largest` function, the code actually runs on the specific values that we
165 pass in.
166
167 The mechanics we went through to get from Listing 10-2 to Listing 10-3 were
168 these steps:
169
170 1. We noticed there was duplicate code.
171 2. We extracted the duplicate code into the body of the function, and specified
172 the inputs and return values of that code in the function signature.
173 3. We replaced the two concrete places that had the duplicated code to call the
174 function instead.
175
176 We can use these same steps with generics to reduce code duplication in
177 different ways in different scenarios. In the same way that the function body
178 is now operating on an abstract `list` instead of concrete values, code using
179 generics will operate on abstract types. The concepts powering generics are the
180 same concepts you already know that power functions, just applied in different
181 ways.
182
183 What if we had two functions, one that found the largest item in a slice of
184 `i32` values and one that found the largest item in a slice of `char` values?
185 How would we get rid of that duplication? Let’s find out!
186
187 ## Generic Data Types
188
189 Using generics where we usually place types, like in function signatures or
190 structs, lets us create definitions that we can use for many different concrete
191 data types. Let’s take a look at how to define functions, structs, enums, and
192 methods using generics, and at the end of this section we’ll discuss the
193 performance of code using generics.
194
195 ### Using Generic Data Types in Function Definitions
196
197 We can define functions that use generics in the signature of the function
198 where the data types of the parameters and return value go. In this way, the
199 code we write can be more flexible and provide more functionality to callers of
200 our function, while not introducing code duplication.
201
202 Continuing with our `largest` function, Listing 10-4 shows two functions
203 providing the same functionality to find the largest value in a slice. The
204 first function is the one we extracted in Listing 10-3 that finds the largest
205 `i32` in a slice. The second function finds the largest `char` in a slice:
206
207 Filename: src/main.rs
208
209 ```
210 fn largest_i32(list: &[i32]) -> i32 {
211 let mut largest = list[0];
212
213 for &item in list.iter() {
214 if item > largest {
215 largest = item;
216 }
217 }
218
219 largest
220 }
221
222 fn largest_char(list: &[char]) -> char {
223 let mut largest = list[0];
224
225 for &item in list.iter() {
226 if item > largest {
227 largest = item;
228 }
229 }
230
231 largest
232 }
233
234 fn main() {
235 let numbers = vec![34, 50, 25, 100, 65];
236
237 let result = largest_i32(&numbers);
238 println!("The largest number is {}", result);
239
240 let chars = vec!['y', 'm', 'a', 'q'];
241
242 let result = largest_char(&chars);
243 println!("The largest char is {}", result);
244 }
245 ```
246
247 Listing 10-4: Two functions that differ only in their names and the types in
248 their signatures
249
250 Here, the functions `largest_i32` and `largest_char` have the exact same body,
251 so it would be nice if we could turn these two functions into one and get rid
252 of the duplication. Luckily, we can do that by introducing a generic type
253 parameter!
254
255 To parameterize the types in the signature of the one function we’re going to
256 define, we need to create a name for the type parameter, just like how we give
257 names for the value parameters to a function. We’re going to choose the name
258 `T`. Any identifier can be used as a type parameter name, but we’re choosing
259 `T` because Rust’s type naming convention is CamelCase. Generic type parameter
260 names also tend to be short by convention, often just one letter. Short for
261 “type”, `T` is the default choice of most Rust programmers.
262
263 When we use a parameter in the body of the function, we have to declare the
264 parameter in the signature so that the compiler knows what that name in the
265 body means. Similarly, when we use a type parameter name in a function
266 signature, we have to declare the type parameter name before we use it. Type
267 name declarations go in angle brackets between the name of the function and the
268 parameter list.
269
270 The function signature of the generic `largest` function we’re going to define
271 will look like this:
272
273 ```
274 fn largest<T>(list: &[T]) -> T {
275 ```
276
277 We would read this as: the function `largest` is generic over some type `T`. It
278 has one parameter named `list`, and the type of `list` is a slice of values of
279 type `T`. The `largest` function will return a value of the same type `T`.
280
281 Listing 10-5 shows the unified `largest` function definition using the generic
282 data type in its signature, and shows how we’ll be able to call `largest` with
283 either a slice of `i32` values or `char` values. Note that this code won’t
284 compile yet!
285
286 Filename: src/main.rs
287
288 ```
289 fn largest<T>(list: &[T]) -> T {
290 let mut largest = list[0];
291
292 for &item in list.iter() {
293 if item > largest {
294 largest = item;
295 }
296 }
297
298 largest
299 }
300
301 fn main() {
302 let numbers = vec![34, 50, 25, 100, 65];
303
304 let result = largest(&numbers);
305 println!("The largest number is {}", result);
306
307 let chars = vec!['y', 'm', 'a', 'q'];
308
309 let result = largest(&chars);
310 println!("The largest char is {}", result);
311 }
312 ```
313
314 Listing 10-5: A definition of the `largest` function that uses generic type
315 parameters but doesn’t compile yet
316
317 If we try to compile this code right now, we’ll get this error:
318
319 ```
320 error[E0369]: binary operation `>` cannot be applied to type `T`
321 |
322 5 | if item > largest {
323 | ^^^^
324 |
325 note: an implementation of `std::cmp::PartialOrd` might be missing for `T`
326 ```
327
328 The note mentions `std::cmp::PartialOrd`, which is a *trait*. We’re going to
329 talk about traits in the next section, but briefly, what this error is saying
330 is that the body of `largest` won’t work for all possible types that `T` could
331 be; since we want to compare values of type `T` in the body, we can only use
332 types that know how to be ordered. The standard library has defined the trait
333 `std::cmp::PartialOrd` that types can implement to enable comparisons. We’ll
334 come back to traits and how to specify that a generic type has a particular
335 trait in the next section, but let’s set this example aside for a moment and
336 explore other places we can use generic type parameters first.
337
338 <!-- Liz: this is the reason we had the topics in the order we did in the first
339 draft of this chapter; it's hard to do anything interesting with generic types
340 in functions unless you also know about traits and trait bounds. I think this
341 ordering could work out okay, though, and keep a stronger thread with the
342 `longest` function going through the whole chapter, but we do pause with a
343 not-yet-compiling example here, which I know isn't ideal either. Let us know
344 what you think. /Carol -->
345
346 ### Using Generic Data Types in Struct Definitions
347
348 We can define structs to use a generic type parameter in one or more of the
349 struct’s fields with the `<>` syntax too. Listing 10-6 shows the definition and
350 use of a `Point` struct that can hold `x` and `y` coordinate values of any type:
351
352 Filename: src/main.rs
353
354 ```
355 struct Point<T> {
356 x: T,
357 y: T,
358 }
359
360 fn main() {
361 let integer = Point { x: 5, y: 10 };
362 let float = Point { x: 1.0, y: 4.0 };
363 }
364 ```
365
366 Listing 10-6: A `Point` struct that holds `x` and `y` values of type `T`
367
368 The syntax is similar to using generics in function definitions. First, we have
369 to declare the name of the type parameter within angle brackets just after the
370 name of the struct. Then we can use the generic type in the struct definition
371 where we would specify concrete data types.
372
373 Note that because we’ve only used one generic type in the definition of
374 `Point`, what we’re saying is that the `Point` struct is generic over some type
375 `T`, and the fields `x` and `y` are *both* that same type, whatever it ends up
376 being. If we try to create an instance of a `Point` that has values of
377 different types, as in Listing 10-7, our code won’t compile:
378
379 Filename: src/main.rs
380
381 ```
382 struct Point<T> {
383 x: T,
384 y: T,
385 }
386
387 fn main() {
388 let wont_work = Point { x: 5, y: 4.0 };
389 }
390 ```
391
392 Listing 10-7: The fields `x` and `y` must be the same type because both have
393 the same generic data type `T`
394
395 If we try to compile this, we’ll get the following error:
396
397 ```
398 error[E0308]: mismatched types
399 -->
400 |
401 7 | let wont_work = Point { x: 5, y: 4.0 };
402 | ^^^ expected integral variable, found
403 floating-point variable
404 |
405 = note: expected type `{integer}`
406 = note: found type `{float}`
407 ```
408
409 When we assigned the integer value 5 to `x`, the compiler then knows for this
410 instance of `Point` that the generic type `T` will be an integer. Then when we
411 specified 4.0 for `y`, which is defined to have the same type as `x`, we get a
412 type mismatch error.
413
414 If we wanted to define a `Point` struct where `x` and `y` could have different
415 types but still have those types be generic, we can use multiple generic type
416 parameters. In listing 10-8, we’ve changed the definition of `Point` to be
417 generic over types `T` and `U`. The field `x` is of type `T`, and the field `y`
418 is of type `U`:
419
420 Filename: src/main.rs
421
422 ```
423 struct Point<T, U> {
424 x: T,
425 y: U,
426 }
427
428 fn main() {
429 let both_integer = Point { x: 5, y: 10 };
430 let both_float = Point { x: 1.0, y: 4.0 };
431 let integer_and_float = Point { x: 5, y: 4.0 };
432 }
433 ```
434
435 Listing 10-8: A `Point` generic over two types so that `x` and `y` may be
436 values of different types
437
438 Now all of these instances of `Point` are allowed! You can use as many generic
439 type parameters in a definition as you want, but using more than a few gets
440 hard to read and understand. If you get to a point of needing lots of generic
441 types, it’s probably a sign that your code could use some restructuring to be
442 separated into smaller pieces.
443
444 ### Using Generic Data Types in Enum Definitions
445
446 Similarly to structs, enums can be defined to hold generic data types in their
447 variants. We used the `Option<T>` enum provided by the standard library in
448 Chapter 6, and now its definition should make more sense. Let’s take another
449 look:
450
451 ```
452 enum Option<T> {
453 Some(T),
454 None,
455 }
456 ```
457
458 In other words, `Option<T>` is an enum generic in type `T`. It has two
459 variants: `Some`, which holds one value of type `T`, and a `None` variant that
460 doesn’t hold any value. The standard library only has to have this one
461 definition to support the creation of values of this enum that have any
462 concrete type. The idea of “an optional value” is a more abstract concept than
463 one specific type, and Rust lets us express this abstract concept without lots
464 of duplication.
465
466 Enums can use multiple generic types as well. The definition of the `Result`
467 enum that we used in Chapter 9 is one example:
468
469 ```
470 enum Result<T, E> {
471 Ok(T),
472 Err(E),
473 }
474 ```
475
476 The `Result` enum is generic over two types, `T` and `E`. `Result` has two
477 variants: `Ok`, which holds a value of type `T`, and `Err`, which holds a value
478 of type `E`. This definition makes it convenient to use the `Result` enum
479 anywhere we have an operation that might succeed (and return a value of some
480 type `T`) or fail (and return an error of some type `E`). Recall Listing 9-2
481 when we opened a file: in that case, `T` was filled in with the type
482 `std::fs::File` when the file was opened successfully and `E` was filled in
483 with the type `std::io::Error` when there were problems opening the file.
484
485 When you recognize situations in your code with multiple struct or enum
486 definitions that differ only in the types of the values they hold, you can
487 remove the duplication by using the same process we used with the function
488 definitions to introduce generic types instead.
489
490 ### Using Generic Data Types in Method Definitions
491
492 Like we did in Chapter 5, we can implement methods on structs and enums that
493 have generic types in their definitions. Listing 10-9 shows the `Point<T>`
494 struct we defined in Listing 10-6. We’ve then defined a method named `x` on
495 `Point<T>` that returns a reference to the data in the field `x`:
496
497 Filename: src/main.rs
498
499 ```
500 struct Point<T> {
501 x: T,
502 y: T,
503 }
504
505 impl<T> Point<T> {
506 fn x(&self) -> &T {
507 &self.x
508 }
509 }
510
511 fn main() {
512 let p = Point { x: 5, y: 10 };
513
514 println!("p.x = {}", p.x());
515 }
516 ```
517
518 Listing 10-9: Implementing a method named `x` on the `Point<T>` struct that
519 will return a reference to the `x` field, which is of type `T`.
520
521 Note that we have to declare `T` just after `impl`, so that we can use it when
522 we specify that we’re implementing methods on the type `Point<T>`.
523
524 Generic type parameters in a struct definition aren’t always the same generic
525 type parameters you want to use in that struct’s method signatures. Listing
526 10-10 defines a method `mixup` on the `Point<T, U>` struct from Listing 10-8.
527 The method takes another `Point` as a parameter, which might have different
528 types than the `self` `Point` that we’re calling `mixup` on. The method creates
529 a new `Point` instance that has the `x` value from the `self` `Point` (which is
530 of type `T`) and the `y` value from the passed-in `Point` (which is of type
531 `W`):
532
533 Filename: src/main.rs
534
535 ```
536 struct Point<T, U> {
537 x: T,
538 y: U,
539 }
540
541 impl<T, U> Point<T, U> {
542 fn mixup<V, W>(&self, other: &Point<V, W>) -> Point<T, W> {
543 Point {
544 x: self.x,
545 y: other.y,
546 }
547 }
548 }
549
550 fn main() {
551 let p1 = Point { x: 5, y: 10.4 };
552 let p2 = Point { x: "Hello", y: 'c'};
553
554 let p3 = p1.mixup(p2);
555
556 println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
557 }
558 ```
559
560 Listing 10-10: Methods that use different generic types than their struct’s
561 definition
562
563 In `main`, we’ve defined a `Point` that has an `i32` for `x` (with value `5`)
564 and an `f64` for `y` (with value `10.4`). `p2` is a `Point` that has a string
565 slice for `x` (with value `"Hello"`) and a `char` for `y` (with value `c`).
566 Calling `mixup` on `p1` with the argument `p2` gives us `p3`, which will have
567 an `i32` for `x`, since `x` came from `p1`. `p3` will have a `char` for `y`,
568 since `y` came from `p2`. The `println!` will print `p3.x = 5, p3.y = c`.
569
570 Note that the generic parameters `T` and `U` are declared after `impl`, since
571 they go with the struct definition. The generic parameters `V` and `W` are
572 declared after `fn mixup`, since they are only relevant to the method.
573
574 ### Performance of Code Using Generics
575
576 You may have been reading this section and wondering if there’s a run-time cost
577 to using generic type parameters. Good news: the way that Rust has implemented
578 generics means that your code will not run any slower than if you had specified
579 concrete types instead of generic type parameters!
580
581 Rust accomplishes this by performing *monomorphization* of code using generics
582 at compile time. Monomorphization is the process of turning generic code into
583 specific code with the concrete types that are actually used filled in.
584
585 What the compiler does is the opposite of the steps that we performed to create
586 the generic function in Listing 10-5. The compiler looks at all the places that
587 generic code is called and generates code for the concrete types that the
588 generic code is called with.
589
590 Let’s work through an example that uses the standard library’s `Option` enum:
591
592 ```
593 let integer = Some(5);
594 let float = Some(5.0);
595 ```
596
597 When Rust compiles this code, it will perform monomorphization. The compiler
598 will read the values that have been passed to `Option` and see that we have two
599 kinds of `Option<T>`: one is `i32`, and one is `f64`. As such, it will expand
600 the generic definition of `Option<T>` into `Option_i32` and `Option_f64`,
601 thereby replacing the generic definition with the specific ones.
602
603 The monomorphized version of our code that the compiler generates looks like
604 this, with the uses of the generic `Option` replaced with the specific
605 definitions created by the compiler:
606
607 Filename: src/main.rs
608
609 ```
610 enum Option_i32 {
611 Some(i32),
612 None,
613 }
614
615 enum Option_f64 {
616 Some(f64),
617 None,
618 }
619
620 fn main() {
621 let integer = Option_i32::Some(5);
622 let float = Option_f64::Some(5.0);
623 }
624 ```
625
626 We can write the non-duplicated code using generics, and Rust will compile that
627 into code that specifies the type in each instance. That means we pay no
628 runtime cost for using generics; when the code runs, it performs just like it
629 would if we had duplicated each particular definition by hand. The process of
630 monomorphization is what makes Rust’s generics extremely efficient at runtime.
631
632 ## Traits: Defining Shared Behavior
633
634 Traits allow us to use another kind of abstraction: they let us abstract over
635 behavior that types can have in common. A *trait* tells the Rust compiler about
636 functionality a particular type has and might share with other types. In
637 situations where we use generic type parameters, we can use *trait bounds* to
638 specify, at compile time, that the generic type may be any type that implements
639 a trait and therefore has the behavior we want to use in that situation.
640
641 > Note: *Traits* are similar to a feature often called ‘interfaces’ in other
642 > languages, though with some differences.
643
644 ### Defining a Trait
645
646 The behavior of a type consists of the methods we can call on that type.
647 Different types share the same behavior if we can call the same methods on all
648 of those types. Trait definitions are a way to group method signatures together
649 in order to define a set of behaviors necessary to accomplish some purpose.
650
651 For example, say we have multiple structs that hold various kinds and amounts
652 of text: a `NewsArticle` struct that holds a news story filed in a particular
653 place in the world, and a `Tweet` that can have at most 140 characters in its
654 content along with metadata like whether it was a retweet or a reply to another
655 tweet.
656
657 We want to make a media aggregator library that can display summaries of data
658 that might be stored in a `NewsArticle` or `Tweet` instance. The behavior we
659 need each struct to have is that it’s able to be summarized, and that we can
660 ask for that summary by calling a `summary` method on an instance. Listing
661 10-11 shows the definition of a `Summarizable` trait that expresses this
662 concept:
663
664 Filename: lib.rs
665
666 ```
667 pub trait Summarizable {
668 fn summary(&self) -> String;
669 }
670 ```
671
672 Listing 10-11: Definition of a `Summarizable` trait that consists of the
673 behavior provided by a `summary` method
674
675 We declare a trait with the `trait` keyword, then the trait’s name, in this
676 case `Summarizable`. Inside curly braces we declare the method signatures that
677 describe the behaviors that types that implement this trait will need to have,
678 in this case `fn summary(&self) -> String`. After the method signature, instead
679 of providing an implementation within curly braces, we put a semicolon. Each
680 type that implements this trait must then provide its own custom behavior for
681 the body of the method, but the compiler will enforce that any type that has
682 the `Summarizable` trait will have the method `summary` defined for it with
683 this signature exactly.
684
685 A trait can have multiple methods in its body, with the method signatures
686 listed one per line and each line ending in a semicolon.
687
688 ### Implementing a Trait on a Type
689
690 Now that we’ve defined the `Summarizable` trait, we can implement it on the
691 types in our media aggregator that we want to have this behavior. Listing 10-12
692 shows an implementation of the `Summarizable` trait on the `NewsArticle` struct
693 that uses the headline, the author, and the location to create the return value
694 of `summary`. For the `Tweet` struct, we’ve chosen to define `summary` as the
695 username followed by the whole text of the tweet, assuming that tweet content
696 is already limited to 140 characters.
697
698 Filename: lib.rs
699
700 ```
701 pub struct NewsArticle {
702 pub headline: String,
703 pub location: String,
704 pub author: String,
705 pub content: String,
706 }
707
708 impl Summarizable for NewsArticle {
709 fn summary(&self) -> String {
710 format!("{}, by {} ({})", self.headline, self.author, self.location)
711 }
712 }
713
714 pub struct Tweet {
715 pub username: String,
716 pub content: String,
717 pub reply: bool,
718 pub retweet: bool,
719 }
720
721 impl Summarizable for Tweet {
722 fn summary(&self) -> String {
723 format!("{}: {}", self.username, self.content)
724 }
725 }
726 ```
727
728 Listing 10-12: Implementing the `Summarizable` trait on the `NewsArticle` and
729 `Tweet` types
730
731 Implementing a trait on a type is similar to implementing methods that aren’t
732 related to a trait. The difference is after `impl`, we put the trait name that
733 we want to implement, then say `for` and the name of the type that we want to
734 implement the trait for. Within the `impl` block, we put the method signatures
735 that the trait definition has defined, but instead of putting a semicolon after
736 each signature, we put curly braces and fill in the method body with the
737 specific behavior that we want the methods of the trait to have for the
738 particular type.
739
740 Once we’ve implemented the trait, we can call the methods on instances of
741 `NewsArticle` and `Tweet` in the same manner that we call methods that aren’t
742 part of a trait:
743
744 ```
745 let tweet = Tweet {
746 username: String::from("horse_ebooks"),
747 content: String::from("of course, as you probably already know, people"),
748 reply: false,
749 retweet: false,
750 };
751
752 println!("1 new tweet: {}", tweet.summary());
753 ```
754
755 This will print `1 new tweet: horse_ebooks: of course, as you probably already
756 know, people`.
757
758 Note that because we’ve defined the `Summarizable` trait and the `NewsArticle`
759 and `Tweet` types all in the same `lib.rs` in Listing 10-12, they’re all in the
760 same scope. If this `lib.rs` is for a crate we’ve called `aggregator`, and
761 someone else wants to use our crate’s functionality plus implement the
762 `Summarizable` trait on their `WeatherForecast` struct, their code would need
763 to import the `Summarizable` trait into their scope first before they could
764 implement it, like in Listing 10-13:
765
766 Filename: lib.rs
767
768 ```
769 extern crate aggregator;
770
771 use aggregator::Summarizable;
772
773 struct WeatherForecast {
774 high_temp: f64,
775 low_temp: f64,
776 chance_of_precipitation: f64,
777 }
778
779 impl Summarizable for WeatherForecast {
780 fn summary(&self) -> String {
781 format!("The high will be {}, and the low will be {}. The chance of
782 precipitation is {}%.", self.high_temp, self.low_temp,
783 self.chance_of_precipitation)
784 }
785 }
786 ```
787
788 Listing 10-13: Bringing the `Summarizable` trait from our `aggregator` crate
789 into scope in another crate
790
791 This code also assumes `Summarizable` is a public trait, which it is because we
792 put the `pub` keyword before `trait` in Listing 10-11.
793
794 One restriction to note with trait implementations: we may implement a trait on
795 a type as long as either the trait or the type are local to our crate. In other
796 words, we aren’t allowed to implement external traits on external types. We
797 can’t implement the `Display` trait on `Vec`, for example, since both `Display`
798 and `Vec` are defined in the standard library. We are allowed to implement
799 standard library traits like `Display` on a custom type like `Tweet` as part of
800 our `aggregator` crate functionality. We could also implement `Summarizable` on
801 `Vec` in our `aggregator` crate, since we’ve defined `Summarizable` there. This
802 restriction is part of what’s called the *orphan rule*, which you can look up
803 if you’re interested in type theory. Briefly, it’s called the orphan rule
804 because the parent type is not present. Without this rule, two crates could
805 implement the same trait for the same type, and the two implementations would
806 conflict: Rust wouldn’t know which implementation to use. Because Rust enforces
807 the orphan rule, other people’s code can’t break your code and vice versa.
808
809 ### Default Implementations
810
811 Sometimes it’s useful to have default behavior for some or all of the methods
812 in a trait, instead of making every implementation on every type define custom
813 behavior. When we implement the trait on a particular type, we can choose to
814 keep or override each method’s default behavior.
815
816 Listing 10-14 shows how we could have chosen to specify a default string for
817 the `summary` method of the `Summarize` trait instead of only choosing to only
818 define the method signature like we did in Listing 10-11:
819
820 Filename: lib.rs
821
822 ```
823 pub trait Summarizable {
824 fn summary(&self) -> String {
825 String::from("(Read more...)")
826 }
827 }
828 ```
829
830 Listing 10-14: Definition of a `Summarizable` trait with a default
831 implementation of the `summary` method
832
833 If we wanted to use this default implementation to summarize instances of
834 `NewsArticle` instead of defining a custom implementation like we did in
835 Listing 10-12, we would specify an empty `impl` block:
836
837 ```
838 impl Summarizable for NewsArticle {}
839 ```
840
841 Even though we’re no longer choosing to define the `summary` method on
842 `NewsArticle` directly, since the `summary` method has a default implementation
843 and we specified that `NewsArticle` implements the `Summarizable` trait, we can
844 still call the `summary` method on an instance of `NewsArticle`:
845
846 ```
847 let article = NewsArticle {
848 headline: String::from("Penguins win the Stanley Cup Championship!"),
849 location: String::from("Pittsburgh, PA, USA"),
850 author: String::from("Iceburgh"),
851 content: String::from("The Pittsburgh Penguins once again are the best
852 hockey team in the NHL."),
853 };
854
855 println!("New article available! {}", article.summary());
856 ```
857
858 This code prints `New article available! (Read more...)`.
859
860 Changing the `Summarizable` trait to have a default implementation for
861 `summary` does not require us to change anything about the implementations of
862 `Summarizable` on `Tweet` in Listing 10-12 or `WeatherForecast` in Listing
863 10-13: the syntax for overriding a default implementation is exactly the same
864 as the syntax for implementing a trait method that doesn’t have a default
865 implementation.
866
867 Default implementations are allowed to call the other methods in the same
868 trait, even if those other methods don’t have a default implementation. In this
869 way, a trait can provide a lot of useful functionality and only require
870 implementers to specify a small part of it. We could choose to have the
871 `Summarizable` trait also have an `author_summary` method whose implementation
872 is required, then a `summary` method that has a default implementation that
873 calls the `author_summary` method:
874
875 ```
876 pub trait Summarizable {
877 fn author_summary(&self) -> String;
878
879 fn summary(&self) -> String {
880 format!("(Read more from {}...)", self.author_summary())
881 }
882 }
883 ```
884
885 In order to use this version of `Summarizable`, we’re only required to define
886 `author_summary` when we implement the trait on a type:
887
888 ```
889 impl Summarizable for Tweet {
890 fn author_summary(&self) -> String {
891 format!("@{}", self.username)
892 }
893 }
894 ```
895
896 Once we define `author_summary`, we can call `summary` on instances of the
897 `Tweet` struct, and the default implementation of `summary` will call the
898 definition of `author_summary` that we’ve provided.
899
900 ```
901 let tweet = Tweet {
902 username: String::from("horse_ebooks"),
903 content: String::from("of course, as you probably already know, people"),
904 reply: false,
905 retweet: false,
906 };
907
908 println!("1 new tweet: {}", tweet.summary());
909 ```
910
911 This will print `1 new tweet: (Read more from @horse_ebooks...)`.
912
913 Note that it is not possible to call the default implementation from an
914 overridden implementation.
915
916 ### Trait Bounds
917
918 Now that we’ve defined traits and implemented those traits on types, we can use
919 traits with generic type parameters. We can constrain generic types so that
920 rather than being any type, the compiler will ensure that the type will be
921 limited to those types that implement a particular trait and thus have the
922 behavior that we need the types to have. This is called specifying *trait
923 bounds* on a generic type.
924
925 For example, in Listing 10-12, we implemented the `Summarizable` trait on the
926 types `NewsArticle` and `Tweet`. We can define a function `notify` that calls
927 the `summary` method on its parameter `item`, which is of the generic type `T`.
928 To be able to call `summary` on `item` without getting an error, we can use
929 trait bounds on `T` to specify that `item` must be of a type that implements
930 the `Summarizable` trait:
931
932 ```
933 pub fn notify<T: Summarizable>(item: T) {
934 println!("Breaking news! {}", item.summary());
935 }
936 ```
937
938 Trait bounds go with the declaration of the generic type parameter, after a
939 colon and within the angle brackets. Because of the trait bound on `T`, we can
940 call `notify` and pass in any instance of `NewsArticle` or `Tweet`. The
941 external code from Listing 10-13 that’s using our `aggregator` crate can call
942 our `notify` function and pass in an instance of `WeatherForecast`, since
943 `Summarizable` is implemented for `WeatherForecast` as well. Code that calls
944 `notify` with any other type, like a `String` or an `i32`, won’t compile, since
945 those types do not implement `Summarizable`.
946
947 We can specify multiple trait bounds on a generic type by using `+`. If we
948 needed to be able to use display formatting on the type `T` in a function as
949 well as the `summary` method, we can use the trait bounds `T: Summarizable +
950 Display`. This means `T` can be any type that implements both `Summarizable`
951 and `Display`.
952
953 For functions that have multiple generic type parameters, each generic has its
954 own trait bounds. Specifying lots of trait bound information in the angle
955 brackets between a function’s name and its parameter list can get hard to read,
956 so there’s an alternate syntax for specifying trait bounds that lets us move
957 them to a `where` clause after the function signature. So instead of:
958
959 ```
960 fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
961 ```
962
963 We can write this instead with a `where` clause:
964
965 ```
966 fn some_function<T, U>(t: T, u: U) -> i32
967 where T: Display + Clone,
968 U: Clone + Debug
969 {
970 ```
971
972 This is less cluttered and makes this function’s signature look more similar to
973 a function without lots of trait bounds, in that the function name, parameter
974 list, and return type are close together.
975
976 ### Fixing the `largest` Function with Trait Bounds
977
978 So any time you want to use behavior defined by a trait on a generic, you need
979 to specify that trait in the generic type parameter’s type bounds. We can now
980 fix the definition of the `largest` function that uses a generic type parameter
981 from Listing 10-5! When we set that code aside, we were getting this error:
982
983 ```
984 error[E0369]: binary operation `>` cannot be applied to type `T`
985 |
986 5 | if item > largest {
987 | ^^^^
988 |
989 note: an implementation of `std::cmp::PartialOrd` might be missing for `T`
990 ```
991
992 In the body of `largest` we wanted to be able to compare two values of type `T`
993 using the greater-than operator. That operator is defined as a default method
994 on the standard library trait `std::cmp::PartialOrd`. So in order to be able to
995 use the greater-than operator, we need to specify `PartialOrd` in the trait
996 bounds for `T` so that the `largest` function will work on slices of any type
997 that can be compared. We don’t need to bring `PartialOrd` into scope because
998 it’s in the prelude.
999
1000 ```
1001 fn largest<T: PartialOrd>(list: &[T]) -> T {
1002 ```
1003
1004 If we try to compile this, we’ll get different errors:
1005
1006 ```
1007 error[E0508]: cannot move out of type `[T]`, a non-copy array
1008 --> src/main.rs:4:23
1009 |
1010 4 | let mut largest = list[0];
1011 | ----------- ^^^^^^^ cannot move out of here
1012 | |
1013 | hint: to prevent move, use `ref largest` or `ref mut largest`
1014
1015 error[E0507]: cannot move out of borrowed content
1016 --> src/main.rs:6:9
1017 |
1018 6 | for &item in list.iter() {
1019 | ^----
1020 | ||
1021 | |hint: to prevent move, use `ref item` or `ref mut item`
1022 | cannot move out of borrowed content
1023 ```
1024
1025 The key to this error is `cannot move out of type [T], a non-copy array`.
1026 With our non-generic versions of the `largest` function, we were only trying to
1027 find the largest `i32` or `char`. As we discussed in Chapter 4, types like
1028 `i32` and `char` that have a known size can be stored on the stack, so they
1029 implement the `Copy` trait. When we changed the `largest` function to be
1030 generic, it’s now possible that the `list` parameter could have types in it
1031 that don’t implement the `Copy` trait, which means we wouldn’t be able to move
1032 the value out of `list[0]` and into the `largest` variable.
1033
1034 If we only want to be able to call this code with types that are `Copy`, we can
1035 add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of
1036 a generic `largest` function that will compile as long as the types of the
1037 values in the slice that we pass into `largest` implement both the `PartialOrd`
1038 and `Copy` traits, like `i32` and `char`:
1039
1040 Filename: src/main.rs
1041
1042 ```
1043 use std::cmp::PartialOrd;
1044
1045 fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
1046 let mut largest = list[0];
1047
1048 for &item in list.iter() {
1049 if item > largest {
1050 largest = item;
1051 }
1052 }
1053
1054 largest
1055 }
1056
1057 fn main() {
1058 let numbers = vec![34, 50, 25, 100, 65];
1059
1060 let result = largest(&numbers);
1061 println!("The largest number is {}", result);
1062
1063 let chars = vec!['y', 'm', 'a', 'q'];
1064
1065 let result = largest(&chars);
1066 println!("The largest char is {}", result);
1067 }
1068 ```
1069
1070 Listing 10-15: A working definition of the `largest` function that works on any
1071 generic type that implements the `PartialOrd` and `Copy` traits
1072
1073 If we don’t want to restrict our `largest` function to only types that
1074 implement the `Copy` trait, we could specify that `T` has the trait bound
1075 `Clone` instead of `Copy` and clone each value in the slice when we want the
1076 `largest` function to have ownership. Using the `clone` function means we’re
1077 potentially making more heap allocations, though, and heap allocations can be
1078 slow if we’re working with large amounts of data. Another way we could
1079 implement `largest` is for the function to return a reference to a `T` value in
1080 the slice. If we change the return type to be `&T` instead of `T` and change
1081 the body of the function to return a reference, we wouldn’t need either the
1082 `Clone` or `Copy` trait bounds and we wouldn’t be doing any heap allocations.
1083 Try implementing these alternate solutions on your own!
1084
1085 Traits and trait bounds let us write code that uses generic type parameters in
1086 order to reduce duplication, but still specify to the compiler exactly what
1087 behavior our code needs the generic type to have. Because we’ve given the trait
1088 bound information to the compiler, it can check that all the concrete types
1089 used with our code provide the right behavior. In dynamically typed languages,
1090 if we tried to call a method on a type that the type didn’t implement, we’d get
1091 an error at runtime. Rust moves these errors to compile time so that we’re
1092 forced to fix the problems before our code is even able to run. Additionally,
1093 we don’t have to write code that checks for behavior at runtime since we’ve
1094 already checked at compile time, which improves performance compared to other
1095 languages without having to give up the flexibility of generics.
1096
1097 There’s another kind of generics that we’ve been using without even realizing
1098 it called *lifetimes*. Rather than helping us ensure that a type has the
1099 behavior we need it to have, lifetimes help us ensure that references are valid
1100 as long as we need them to be. Let’s learn how lifetimes do that.
1101
1102 ## Validating References with Lifetimes
1103
1104 When we talked about references in Chapter 4, we left out an important detail:
1105 every reference in Rust has a *lifetime*, which is the scope for which that
1106 reference is valid. Most of the time lifetimes are implicit and inferred, just
1107 like most of the time types are inferred. Similarly to when we have to annotate
1108 types because multiple types are possible, there are cases where the lifetimes
1109 of references could be related in a few different ways, so Rust needs us to
1110 annotate the relationships using generic lifetime parameters so that it can
1111 make sure the actual references used at runtime will definitely be valid.
1112
1113 Yes, it’s a bit unusual, and will be different to tools you’ve used in other
1114 programming languages. Lifetimes are, in some ways, Rust’s most distinctive
1115 feature.
1116
1117 Lifetimes are a big topic that can’t be covered in entirety in this chapter, so
1118 we’ll cover common ways you might encounter lifetime syntax in this chapter to
1119 get you familiar with the concepts. Chapter 19 will contain more advanced
1120 information about everything lifetimes can do.
1121
1122 ### Lifetimes Prevent Dangling References
1123
1124 The main aim of lifetimes is to prevent dangling references, which will cause a
1125 program to reference data other than the data we’re intending to reference.
1126 Consider the program in Listing 10-16, with an outer scope and an inner scope.
1127 The outer scope declares a variable named `r` with no initial value, and the
1128 inner scope declares a variable named `x` with the initial value of 5. Inside
1129 the inner scope, we attempt to set the value of `r` as a reference to `x`. Then
1130 the inner scope ends, and we attempt to print out the value in `r`:
1131
1132 ```
1133 {
1134 let r;
1135
1136 {
1137 let x = 5;
1138 r = &x;
1139 }
1140
1141 println!("r: {}", r);
1142 }
1143 ```
1144
1145 Listing 10-16: An attempt to use a reference whose value has gone out of scope
1146
1147 > #### Uninitialized Variables Cannot Be Used
1148 >
1149 > The next few examples declare variables without giving them an initial value,
1150 > so that the variable name exists in the outer scope. This might appear to be
1151 > in conflict with Rust not having null. However, if we try to use a variable
1152 > before giving it a value, we’ll get a compile-time error. Try it out!
1153
1154 When we compile this code, we’ll get an error:
1155
1156 ```
1157 error: `x` does not live long enough
1158 |
1159 6 | r = &x;
1160 | - borrow occurs here
1161 7 | }
1162 | ^ `x` dropped here while still borrowed
1163 ...
1164 10 | }
1165 | - borrowed value needs to live until here
1166 ```
1167
1168 The variable `x` doesn’t “live long enough.” Why not? Well, `x` is going to go
1169 out of scope when we hit the closing curly brace on line 7, ending the inner
1170 scope. But `r` is valid for the outer scope; its scope is larger and we say
1171 that it “lives longer.” If Rust allowed this code to work, `r` would be
1172 referencing memory that was deallocated when `x` went out of scope, and
1173 anything we tried to do with `r` wouldn’t work correctly. So how does Rust
1174 determine that this code should not be allowed?
1175
1176 #### The Borrow Checker
1177
1178 The part of the compiler called the *borrow checker* compares scopes to
1179 determine that all borrows are valid. Listing 10-17 shows the same example from
1180 Listing 10-16 with annotations showing the lifetimes of the variables:
1181
1182 ```
1183 {
1184 let r; // -------+-- 'a
1185 // |
1186 { // |
1187 let x = 5; // -+-----+-- 'b
1188 r = &x; // | |
1189 } // -+ |
1190 // |
1191 println!("r: {}", r); // |
1192 // |
1193 // -------+
1194 }
1195 ```
1196
1197 Listing 10-17: Annotations of the lifetimes of `x` and `r`, named `'a` and `'b`
1198 respectively
1199
1200 <!-- Just checking I'm reading this right: the inside block is the b lifetime,
1201 correct? I want to leave a note for production, make sure we can make that
1202 clear -->
1203 <!-- Yes, the inside block for the `'b` lifetime starts with the `let x = 5;`
1204 line and ends with the first closing curly brace on the 7th line. Do you think
1205 the text art comments work or should we make an SVG diagram that has nicer
1206 looking arrows and labels? /Carol -->
1207
1208 We’ve annotated the lifetime of `r` with `'a` and the lifetime of `x` with
1209 `'b`. As you can see, the inner `'b` block is much smaller than the outer `'a`
1210 lifetime block. At compile time, Rust compares the size of the two lifetimes
1211 and sees that `r` has a lifetime of `'a`, but that it refers to an object with
1212 a lifetime of `'b`. The program is rejected because the lifetime `'b` is
1213 shorter than the lifetime of `'a`: the subject of the reference does not live
1214 as long as the reference.
1215
1216 Let’s look at an example in Listing 10-18 that doesn’t try to make a dangling
1217 reference and compiles without any errors:
1218
1219 ```
1220 {
1221 let x = 5; // -----+-- 'b
1222 // |
1223 let r = &x; // --+--+-- 'a
1224 // | |
1225 println!("r: {}", r); // | |
1226 // --+ |
1227 } // -----+
1228 ```
1229
1230 Listing 10-18: A valid reference because the data has a longer lifetime than
1231 the reference
1232
1233 Here, `x` has the lifetime `'b`, which in this case is larger than `'a`. This
1234 means `r` can reference `x`: Rust knows that the reference in `r` will always
1235 be valid while `x` is valid.
1236
1237 Now that we’ve shown where the lifetimes of references are in a concrete
1238 example and discussed how Rust analyzes lifetimes to ensure references will
1239 always be valid, let’s talk about generic lifetimes of parameters and return
1240 values in the context of functions.
1241
1242 ### Generic Lifetimes in Functions
1243
1244 Let’s write a function that will return the longest of two string slices. We
1245 want to be able to call this function by passing it two string slices, and we
1246 want to get back a string slice. The code in Listing 10-19 should print `The
1247 longest string is abcd` once we’ve implemented the `longest` function:
1248
1249 Filename: src/main.rs
1250
1251 ```
1252 fn main() {
1253 let string1 = String::from("abcd");
1254 let string2 = "xyz";
1255
1256 let result = longest(string1.as_str(), string2);
1257 println!("The longest string is {}", result);
1258 }
1259 ```
1260
1261 Listing 10-19: A `main` function that calls the `longest` function to find the
1262 longest of two string slices
1263
1264 Note that we want the function to take string slices (which are references, as
1265 we talked about in Chapter 4) since we don’t want the `longest` function to
1266 take ownership of its arguments. We want the function to be able to accept
1267 slices of a `String` (which is the type of the variable `string1`) as well as
1268 string literals (which is what variable `string2` contains).
1269
1270 <!-- why is `a` a slice and `b` a literal? You mean "a" from the string "abcd"? -->
1271 <!-- I've changed the variable names to remove ambiguity between the variable
1272 name `a` and the "a" from the string "abcd". `string1` is not a slice, it's a
1273 `String`, but we're going to pass a slice that refers to that `String` to the
1274 `longest` function (`string1.as_str()` creates a slice that references the
1275 `String` stored in `string1`). We chose to have `string2` be a literal since
1276 the reader might have code with both `String`s and string literals, and the way
1277 most readers first get into problems with lifetimes is involving string slices,
1278 so we wanted to demonstrate the flexibility of taking string slices as
1279 arguments but the issues you might run into because string slices are
1280 references.
1281 All of the `String`/string slice/string literal concepts here are covered
1282 thoroughly in Chapter 4, which is why we put two back references here (above
1283 and below). If these topics are confusing you in this context, I'd be
1284 interested to know if rereading Chapter 4 clears up that confusion.
1285 /Carol -->
1286
1287 Refer back to the “String Slices as Arguments” section of Chapter 4 for more
1288 discussion about why these are the arguments we want.
1289
1290 If we try to implement the `longest` function as shown in Listing 10-20, it
1291 won’t compile:
1292
1293 Filename: src/main.rs
1294
1295 ```
1296 fn longest(x: &str, y: &str) -> &str {
1297 if x.len() > y.len() {
1298 x
1299 } else {
1300 y
1301 }
1302 }
1303 ```
1304
1305 Listing 10-20: An implementation of the `longest` function that returns the
1306 longest of two string slices, but does not yet compile
1307
1308 Instead we get the following error that talks about lifetimes:
1309
1310 ```
1311 error[E0106]: missing lifetime specifier
1312 |
1313 1 | fn longest(x: &str, y: &str) -> &str {
1314 | ^ expected lifetime parameter
1315 |
1316 = help: this function's return type contains a borrowed value, but the
1317 signature does not say whether it is borrowed from `x` or `y`
1318 ```
1319
1320 The help text is telling us that the return type needs a generic lifetime
1321 parameter on it because Rust can’t tell if the reference being returned refers
1322 to `x` or `y`. Actually, we don’t know either, since the `if` block in the body
1323 of this function returns a reference to `x` and the `else` block returns a
1324 reference to `y`!
1325
1326 As we’re defining this function, we don’t know the concrete values that will be
1327 passed into this function, so we don’t know whether the `if` case or the `else`
1328 case will execute. We also don’t know the concrete lifetimes of the references
1329 that will be passed in, so we can’t look at the scopes like we did in Listings
1330 10-17 and 10-18 in order to determine that the reference we return will always
1331 be valid. The borrow checker can’t determine this either, because it doesn’t
1332 know how the lifetimes of `x` and `y` relate to the lifetime of the return
1333 value. We’re going to add generic lifetime parameters that will define the
1334 relationship between the references so that the borrow checker can perform its
1335 analysis.
1336
1337 ### Lifetime Annotation Syntax
1338
1339 Lifetime annotations don’t change how long any of the references involved live.
1340 In the same way that functions can accept any type when the signature specifies
1341 a generic type parameter, functions can accept references with any lifetime
1342 when the signature specifies a generic lifetime parameter. What lifetime
1343 annotations do is relate the lifetimes of multiple references to each other.
1344
1345 Lifetime annotations have a slightly unusual syntax: the names of lifetime
1346 parameters must start with an apostrophe `'`. The names of lifetime parameters
1347 are usually all lowercase, and like generic types, their names are usually very
1348 short. `'a` is the name most people use as a default. Lifetime parameter
1349 annotations go after the `&` of a reference, and a space separates the lifetime
1350 annotation from the reference’s type.
1351
1352 Here’s some examples: we’ve got a reference to an `i32` without a lifetime
1353 parameter, a reference to an `i32` that has a lifetime parameter named `'a`,
1354 and a mutable reference to an `i32` that also has the lifetime `'a`:
1355
1356 ```
1357 &i32 // a reference
1358 &'a i32 // a reference with an explicit lifetime
1359 &'a mut i32 // a mutable reference with an explicit lifetime
1360 ```
1361
1362 One lifetime annotation by itself doesn’t have much meaning: lifetime
1363 annotations tell Rust how the generic lifetime parameters of multiple
1364 references relate to each other. If we have a function with the parameter
1365 `first` that is a reference to an `i32` that has the lifetime `'a`, and the
1366 function has another parameter named `second` that is another reference to an
1367 `i32` that also has the lifetime `'a`, these two lifetime annotations that have
1368 the same name indicate that the references `first` and `second` must both live
1369 as long as the same generic lifetime.
1370
1371 ### Lifetime Annotations in Function Signatures
1372
1373 Let’s look at lifetime annotations in the context of the `longest` function
1374 we’re working on. Just like generic type parameters, generic lifetime
1375 parameters need to be declared within angle brackets between the function name
1376 and the parameter list. The constraint we want to tell Rust about for the
1377 references in the parameters and the return value is that they all must have
1378 the same lifetime, which we’ll name `'a` and add to each reference as shown in
1379 Listing 10-21:
1380
1381 Filename: src/main.rs
1382
1383 ```
1384 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
1385 if x.len() > y.len() {
1386 x
1387 } else {
1388 y
1389 }
1390 }
1391 ```
1392
1393 Listing 10-21: The `longest` function definition that specifies all the
1394 references in the signature must have the same lifetime, `'a`
1395
1396 This will compile and will produce the result we want when used with the `main`
1397 function in Listing 10-19.
1398
1399 The function signature now says that for some lifetime `'a`, the function will
1400 get two parameters, both of which are string slices that live at least as long
1401 as the lifetime `'a`. The function will return a string slice that also will
1402 last at least as long as the lifetime `'a`. This is the contract we are telling
1403 Rust we want it to enforce.
1404
1405 By specifying the lifetime parameters in this function signature, we are not
1406 changing the lifetimes of any values passed in or returned, but we are saying
1407 that any values that do not adhere to this contract should be rejected by the
1408 borrow checker. This function does not know (or need to know) exactly how long
1409 `x` and `y` will live, but only needs to knows that there is some scope that
1410 can be substituted for `'a` that will satisfy this signature.
1411
1412 When annotating lifetimes in functions, the annotations go on the function
1413 signature, and not in any of the code in the function body. This is because
1414 Rust is able analyze the code within the function without any help, but when a
1415 function has references to or from code outside that function, the lifetimes of
1416 the arguments or return values will potentially be different each time the
1417 function is called. This would be incredibly costly and often impossible for
1418 Rust to figure out. In this case, we need to annotate the lifetimes ourselves.
1419
1420 When concrete references are passed to `longest`, the concrete lifetime that
1421 gets substituted for `'a` is the part of the scope of `x` that overlaps with
1422 the scope of `y`. Since scopes always nest, another way to say this is that the
1423 generic lifetime `'a` will get the concrete lifetime equal to the smaller of
1424 the lifetimes of `x` and `y`. Because we’ve annotated the returned reference
1425 with the same lifetime parameter `'a`, the returned reference will therefore be
1426 guaranteed to be valid as long as the shorter of the lifetimes of `x` and `y`.
1427
1428 Let’s see how this restricts the usage of the `longest` function by passing in
1429 references that have different concrete lifetimes. Listing 10-22 is a
1430 straightforward example that should match your intuition from any language:
1431 `string1` is valid until the end of the outer scope, `string2` is valid until
1432 the end of the inner scope, and `result` references something that is valid
1433 until the end of the outer scope. The borrow checker approves of this code; it
1434 will compile and print `The longest string is long string is long` when run:
1435
1436 Filename: src/main.rs
1437
1438 ```
1439 fn main() {
1440 let string1 = String::from("long string is long");
1441
1442 {
1443 let string2 = String::from("xyz");
1444 let result = longest(string1.as_str(), string2.as_str());
1445 println!("The longest string is {}", result);
1446 }
1447 }
1448 ```
1449
1450 Listing 10-22: Using the `longest` function with references to `String` values
1451 that have different concrete lifetimes
1452
1453 Next, let’s try an example that will show that the lifetime of the reference in
1454 `result` must be the smaller lifetime of the two arguments. We’ll move the
1455 declaration of the `result` variable outside the inner scope, but leave the
1456 assignment of the value to the `result` variable inside the scope with
1457 `string2`. Next, we’ll move the `println!` that uses `result` outside of the
1458 inner scope, after it has ended. The code in Listing 10-23 will not compile:
1459
1460 Filename: src/main.rs
1461
1462 ```
1463 fn main() {
1464 let string1 = String::from("long string is long");
1465 let result;
1466 {
1467 let string2 = String::from("xyz");
1468 result = longest(string1.as_str(), string2.as_str());
1469 }
1470 println!("The longest string is {}", result);
1471 }
1472 ```
1473
1474 Listing 10-23: Attempting to use `result` after `string2` has gone out of scope
1475 won’t compile
1476
1477 If we try to compile this, we’ll get this error:
1478
1479 ```
1480 error: `string2` does not live long enough
1481 |
1482 6 | result = longest(string1.as_str(), string2.as_str());
1483 | ------- borrow occurs here
1484 7 | }
1485 | ^ `string2` dropped here while still borrowed
1486 8 | println!("The longest string is {}", result);
1487 9 | }
1488 | - borrowed value needs to live until here
1489 ```
1490
1491 The error is saying that in order for `result` to be valid for the `println!`,
1492 `string2` would need to be valid until the end of the outer scope. Rust knows
1493 this because we annotated the lifetimes of the function parameters and return
1494 values with the same lifetime parameter, `'a`.
1495
1496 We can look at this code as humans and see that `string1` is longer, and
1497 therefore `result` will contain a reference to `string1`. Because `string1` has
1498 not gone out of scope yet, a reference to `string1` will still be valid for the
1499 `println!`. However, what we’ve told Rust with the lifetime parameters is that
1500 the lifetime of the reference returned by the `longest` function is the same as
1501 the smaller of the lifetimes of the references passed in. Therefore, the borrow
1502 checker disallows the code in Listing 10-23 as possibly having an invalid
1503 reference.
1504
1505 Try designing some more experiments that vary the values and lifetimes of the
1506 references passed in to the `longest` function and how the returned reference
1507 is used. Make hypotheses about whether your experiments will pass the borrow
1508 checker or not before you compile, then check to see if you’re right!
1509
1510 ### Thinking in Terms of Lifetimes
1511
1512 The exact way to specify lifetime parameters depends on what your function is
1513 doing. For example, if we changed the implementation of the `longest` function
1514 to always return the first argument rather than the longest string slice, we
1515 wouldn’t need to specify a lifetime on the `y` parameter. This code compiles:
1516
1517 Filename: src/main.rs
1518
1519 ```
1520 fn longest<'a>(x: &'a str, y: &str) -> &'a str {
1521 x
1522 }
1523 ```
1524
1525 In this example, we’ve specified a lifetime parameter `'a` for the parameter
1526 `x` and the return type, but not for the parameter `y`, since the lifetime of
1527 `y` does not have any relationship with the lifetime of `x` or the return value.
1528
1529 When returning a reference from a function, the lifetime parameter for the
1530 return type needs to match the lifetime parameter of one of the arguments. If
1531 the reference returned does *not* refer to one of the arguments, the only other
1532 possibility is that it refers to a value created within this function, which
1533 would be a dangling reference since the value will go out of scope at the end
1534 of the function. Consider this attempted implementation of the `longest`
1535 function that won’t compile:
1536
1537 Filename: src/main.rs
1538
1539 ```
1540 fn longest<'a>(x: &str, y: &str) -> &'a str {
1541 let result = String::from("really long string");
1542 result.as_str()
1543 }
1544 ```
1545
1546 Even though we’ve specified a lifetime parameter `'a` for the return type, this
1547 implementation fails to compile because the return value lifetime is not
1548 related to the lifetime of the parameters at all. Here’s the error message we
1549 get:
1550
1551 ```
1552 error: `result` does not live long enough
1553 |
1554 3 | result.as_str()
1555 | ^^^^^^ does not live long enough
1556 4 | }
1557 | - borrowed value only lives until here
1558 |
1559 note: borrowed value must be valid for the lifetime 'a as defined on the block
1560 at 1:44...
1561 |
1562 1 | fn longest<'a>(x: &str, y: &str) -> &'a str {
1563 | ^
1564 ```
1565
1566 The problem is that `result` will go out of scope and get cleaned up at the end
1567 of the `longest` function, and we’re trying to return a reference to `result`
1568 from the function. There’s no way we can specify lifetime parameters that would
1569 change the dangling reference, and Rust won’t let us create a dangling
1570 reference. In this case, the best fix would be to return an owned data type
1571 rather than a reference so that the calling function is then responsible for
1572 cleaning up the value.
1573
1574 Ultimately, lifetime syntax is about connecting the lifetimes of various
1575 arguments and return values of functions. Once they’re connected, Rust has
1576 enough information to allow memory-safe operations and disallow operations that
1577 would create dangling pointers or otherwise violate memory safety.
1578
1579 ### Lifetime Annotations in Struct Definitions
1580
1581 Up until now, we’ve only defined structs to hold owned types. It is possible
1582 for structs to hold references, but we need to add a lifetime annotation on
1583 every reference in the struct’s definition. Listing 10-24 has a struct named
1584 `ImportantExcerpt` that holds a string slice:
1585
1586 Filename: src/main.rs
1587
1588 ```
1589 struct ImportantExcerpt<'a> {
1590 part: &'a str,
1591 }
1592
1593 fn main() {
1594 let novel = String::from("Call me Ishmael. Some years ago...");
1595 let first_sentence = novel.split('.')
1596 .next()
1597 .expect("Could not find a '.'");
1598 let i = ImportantExcerpt { part: first_sentence };
1599 }
1600 ```
1601
1602 Listing 10-24: A struct that holds a reference, so its definition needs a
1603 lifetime annotation
1604
1605 This struct has one field, `part`, that holds a string slice, which is a
1606 reference. Just like with generic data types, we have to declare the name of
1607 the generic lifetime parameter inside angle brackets after the name of the
1608 struct so that we can use the lifetime parameter in the body of the struct
1609 definition.
1610
1611 The `main` function here creates an instance of the `ImportantExcerpt` struct
1612 that holds a reference to the first sentence of the `String` owned by the
1613 variable `novel`.
1614
1615 ### Lifetime Elision
1616
1617 In this section, we’ve learned that every reference has a lifetime, and we need
1618 to specify lifetime parameters for functions or structs that use references.
1619 However, in Chapter 4 we had a function in the “String Slices” section, shown
1620 again in Listing 10-25, that compiled without lifetime annotations:
1621
1622 Filename: src/lib.rs
1623
1624 ```
1625 fn first_word(s: &str) -> &str {
1626 let bytes = s.as_bytes();
1627
1628 for (i, &item) in bytes.iter().enumerate() {
1629 if item == b' ' {
1630 return &s[0..i];
1631 }
1632 }
1633
1634 &s[..]
1635 }
1636 ```
1637
1638 Listing 10-25: A function we defined in Chapter 4 that compiled without
1639 lifetime annotations, even though the parameter and return type are references
1640
1641 The reason this function compiles without lifetime annotations is historical:
1642 in early versions of pre-1.0 Rust, this indeed wouldn’t have compiled. Every
1643 reference needed an explicit lifetime. At that time, the function signature
1644 would have been written like this:
1645
1646 ```
1647 fn first_word<'a>(s: &'a str) -> &'a str {
1648 ```
1649
1650 After writing a lot of Rust code, the Rust team found that Rust programmers
1651 were typing the same lifetime annotations over and over in particular
1652 situations. These situations were predictable and followed a few deterministic
1653 patterns. The Rust team then programmed these patterns into the Rust compiler’s
1654 code so that the borrow checker can infer the lifetimes in these situations
1655 without forcing the programmer to explicitly add the annotations.
1656
1657 We mention this piece of Rust history because it’s entirely possible that more
1658 deterministic patterns will emerge and be added to the compiler. In the future,
1659 even fewer lifetime annotations might be required.
1660
1661 The patterns programmed into Rust’s analysis of references are called the
1662 *lifetime elision rules*. These aren’t rules for programmers to follow; the
1663 rules are a set of particular cases that the compiler will consider, and if
1664 your code fits these cases, you don’t need to write the lifetimes explicitly.
1665
1666 The elision rules don’t provide full inference: if Rust deterministically
1667 applies the rules but there’s still ambiguity as to what lifetimes the
1668 references have, it won’t guess what the lifetime of the remaining references
1669 should be. In this case, the compiler will give you an error that can be
1670 resolved by adding the lifetime annotations that correspond to your intentions
1671 for how the references relate to each other.
1672
1673 First, some definitions: Lifetimes on function or method parameters are called
1674 *input lifetimes*, and lifetimes on return values are called *output lifetimes*.
1675
1676 Now, on to the rules that the compiler uses to figure out what lifetimes
1677 references have when there aren’t explicit annotations. The first rule applies
1678 to input lifetimes, and the second two rules apply to output lifetimes. If the
1679 compiler gets to the end of the three rules and there are still references that
1680 it can’t figure out lifetimes for, the compiler will stop with an error.
1681
1682 1. Each parameter that is a reference gets its own lifetime parameter. In other
1683 words, a function with one parameter gets one lifetime parameter: `fn
1684 foo<'a>(x: &'a i32)`, a function with two arguments gets two separate
1685 lifetime parameters: `fn foo<'a, 'b>(x: &'a i32, y: &'b i32)`, and so on.
1686
1687 2. If there is exactly one input lifetime parameter, that lifetime is assigned
1688 to all output lifetime parameters: `fn foo<'a>(x: &'a i32) -> &'a i32`.
1689
1690 3. If there are multiple input lifetime parameters, but one of them is `&self`
1691 or `&mut self` because this is a method, then the lifetime of `self` is
1692 assigned to all output lifetime parameters. This makes writing methods much
1693 nicer.
1694
1695 Let’s pretend we’re the compiler and apply these rules to figure out what the
1696 lifetimes of the references in the signature of the `first_word` function in
1697 Listing 10-25 are. The signatures starts without any lifetimes associated with
1698 the references:
1699
1700 ```
1701 fn first_word(s: &str) -> &str {
1702 ```
1703
1704 Then we (as the compiler) apply the first rule, which says each parameter gets
1705 its own lifetime. We’re going to call it `'a` as usual, so now the signature is:
1706
1707 ```
1708 fn first_word<'a>(s: &'a str) -> &str {
1709 ```
1710
1711 On to the second rule, which applies because there is exactly one input
1712 lifetime. The second rule says the lifetime of the one input parameter gets
1713 assigned to the output lifetime, so now the signature is:
1714
1715 ```
1716 fn first_word<'a>(s: &'a str) -> &'a str {
1717 ```
1718
1719 Now all the references in this function signature have lifetimes, and the
1720 compiler can continue its analysis without needing the programmer to annotate
1721 the lifetimes in this function signature.
1722
1723 Let’s do another example, this time with the `longest` function that had no
1724 lifetime parameters when we started working with in Listing 10-20:
1725
1726 ```
1727 fn longest(x: &str, y: &str) -> &str {
1728 ```
1729
1730 Pretending we’re the compiler again, let’s apply the first rule: each parameter
1731 gets its own lifetime. This time we have two parameters, so we have two
1732 lifetimes:
1733
1734 ```
1735 fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &str {
1736 ```
1737
1738 Looking at the second rule, it doesn’t apply since there is more than one input
1739 lifetime. Looking at the third rule, this also does not apply because this is a
1740 function rather than a method, so none of the parameters are `self`. So we’re
1741 out of rules, but we haven’t figured out what the return type’s lifetime is.
1742 This is why we got an error trying to compile the code from Listing 10-20: the
1743 compiler worked through the lifetime elision rules it knows, but still can’t
1744 figure out all the lifetimes of the references in the signature.
1745
1746 Because the third rule only really applies in method signatures, let’s look at
1747 lifetimes in that context now, and see why the third rule means we don’t have
1748 to annotate lifetimes in method signatures very often.
1749
1750 ### Lifetime Annotations in Method Definitions
1751
1752 <!-- Is this different to the reference lifetime annotations, or just a
1753 finalized explanation? -->
1754 <!-- This is about lifetimes on references in method signatures, which is where
1755 the 3rd lifetime elision rule kicks in. It can also be confusing where lifetime
1756 parameters need to be declared and used since the lifetime parameters could go
1757 with the struct's fields or with references passed into or returned from
1758 methods. /Carol -->
1759
1760 When we implement methods on a struct with lifetimes, the syntax is again the
1761 same as that of generic type parameters that we showed in Listing 10-10: the
1762 place that lifetime parameters are declared and used depends on whether the
1763 lifetime parameter is related to the struct fields or the method arguments and
1764 return values.
1765
1766 Lifetime names for struct fields always need to be declared after the `impl`
1767 keyword and then used after the struct’s name, since those lifetimes are part
1768 of the struct’s type.
1769
1770 In method signatures inside the `impl` block, references might be tied to the
1771 lifetime of references in the struct’s fields, or they might be independent. In
1772 addition, the lifetime elision rules often make it so that lifetime annotations
1773 aren’t necessary in method signatures. Let’s look at some examples using the
1774 struct named `ImportantExcerpt` that we defined in Listing 10-24.
1775
1776 First, here’s a method named `level`. The only parameter is a reference to
1777 `self`, and the return value is just an `i32`, not a reference to anything:
1778
1779 ```
1780 impl<'a> ImportantExcerpt<'a> {
1781 fn level(&self) -> i32 {
1782 3
1783 }
1784 }
1785 ```
1786
1787 The lifetime parameter declaration after `impl` and use after the type name is
1788 required, but we’re not required to annotate the lifetime of the reference to
1789 `self` because of the first elision rule.
1790
1791 Here’s an example where the third lifetime elision rule applies:
1792
1793 ```
1794 impl<'a> ImportantExcerpt<'a> {
1795 fn announce_and_return_part(&self, announcement: &str) -> &str {
1796 println!("Attention please: {}", announcement);
1797 self.part
1798 }
1799 }
1800 ```
1801
1802 There are two input lifetimes, so Rust applies the first lifetime elision rule
1803 and gives both `&self` and `announcement` their own lifetimes. Then, because
1804 one of the parameters is `&self`, the return type gets the lifetime of `&self`,
1805 and all lifetimes have been accounted for.
1806
1807 ### The Static Lifetime
1808
1809 There is *one* special lifetime we need to discuss: `'static`. The `'static`
1810 lifetime is the entire duration of the program. All string literals have the
1811 `'static` lifetime, which we can choose to annotate as follows:
1812
1813 ```
1814 let s: &'static str = "I have a static lifetime.";
1815 ```
1816
1817 The text of this string is stored directly in the binary of your program and
1818 the binary of your program is always available. Therefore, the lifetime of all
1819 string literals is `'static`.
1820
1821 <!-- How would you add a static lifetime (below)? -->
1822 <!-- Just like you'd specify any lifetime, see above where it shows `&'static str`. /Carol -->
1823
1824 You may see suggestions to use the `'static` lifetime in error message help
1825 text, but before specifying `'static` as the lifetime for a reference, think
1826 about whether the reference you have is one that actually lives the entire
1827 lifetime of your program or not (or even if you want it to live that long, if
1828 it could). Most of the time, the problem in the code is an attempt to create a
1829 dangling reference or a mismatch of the available lifetimes, and the solution
1830 is fixing those problems, not specifying the `'static` lifetime.
1831
1832 ### Generic Type Parameters, Trait Bounds, and Lifetimes Together
1833
1834 Let’s briefly look at the syntax of specifying generic type parameters, trait
1835 bounds, and lifetimes all in one function!
1836
1837 ```
1838 use std::fmt::Display;
1839
1840 fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
1841 where T: Display
1842 {
1843 println!("Announcement! {}", ann);
1844 if x.len() > y.len() {
1845 x
1846 } else {
1847 y
1848 }
1849 }
1850 ```
1851
1852 This is the `longest` function from Listing 10-21 that returns the longest of
1853 two string slices, but with an extra argument named `ann`. The type of `ann` is
1854 the generic type `T`, which may be filled in by any type that implements the
1855 `Display` trait as specified by the `where` clause. This extra argument will be
1856 printed out before the function compares the lengths of the string slices,
1857 which is why the `Display` trait bound is necessary. Because lifetimes are a
1858 type of generic, the declarations of both the lifetime parameter `'a` and the
1859 generic type parameter `T` go in the same list within the angle brackets after
1860 the function name.
1861
1862 ## Summary
1863
1864 We covered a lot in this chapter! Now that you know about generic type
1865 parameters, traits and trait bounds, and generic lifetime parameters, you’re
1866 ready to write code that isn’t duplicated but can be used in many different
1867 situations. Generic type parameters mean the code can be applied to different
1868 types. Traits and trait bounds ensure that even though the types are generic,
1869 those types will have the behavior the code needs. Relationships between the
1870 lifetimes of references specified by lifetime annotations ensure that this
1871 flexible code won’t have any dangling references. And all of this happens at
1872 compile time so that run-time performance isn’t affected!
1873
1874 Believe it or not, there’s even more to learn in these areas: Chapter 17 will
1875 discuss trait objects, which are another way to use traits. Chapter 19 will be
1876 covering more complex scenarios involving lifetime annotations. Chapter 20 will
1877 get to some advanced type system features. Up next, though, let’s talk about
1878 how to write tests in Rust so that we can make sure our code using all these
1879 features is working the way we want it to!