]> git.lizzy.rs Git - rust.git/blob - src/doc/guide-lifetimes.md
auto merge of #15746 : steveklabnik/rust/docs_random, r=alexcrichton
[rust.git] / src / doc / guide-lifetimes.md
1 % The Rust References and Lifetimes Guide
2
3 # Introduction
4
5 References are one of the more flexible and powerful tools available in
6 Rust. They can point anywhere: into the heap, stack, and even into the
7 interior of another data structure. A reference is as flexible as a C pointer
8 or C++ reference.
9
10 Unlike C and C++ compilers, the Rust compiler includes special static
11 checks that ensure that programs use references safely.
12
13 Despite their complete safety, a reference's representation at runtime
14 is the same as that of an ordinary pointer in a C program. They introduce zero
15 overhead. The compiler does all safety checks at compile time.
16
17 Although references have rather elaborate theoretical underpinnings
18 (e.g. region pointers), the core concepts will be familiar to anyone
19 who has worked with C or C++. The best way to explain how they are
20 used—and their limitations—is probably just to work through several examples.
21
22 # By example
23
24 References, sometimes known as *borrowed pointers*, are only valid for
25 a limited duration. References never claim any kind of ownership
26 over the data that they point to. Instead, they are used for cases
27 where you would like to use data for a short time.
28
29 Consider a simple struct type `Point`:
30
31 ~~~
32 struct Point {x: f64, y: f64}
33 ~~~
34
35 We can use this simple definition to allocate points in many different ways. For
36 example, in this code, each of these local variables contains a point,
37 but allocated in a different place:
38
39 ~~~
40 # struct Point {x: f64, y: f64}
41 let on_the_stack : Point      =     Point {x: 3.0, y: 4.0};
42 let on_the_heap  : Box<Point> = box Point {x: 7.0, y: 9.0};
43 ~~~
44
45 Suppose we wanted to write a procedure that computed the distance between any
46 two points, no matter where they were stored. One option is to define a function
47 that takes two arguments of type `Point`—that is, it takes the points by value.
48 But if we define it this way, calling the function will cause the points to be
49 copied. For points, this is probably not so bad, but often copies are
50 expensive. So we'd like to define a function that takes the points just as
51 a reference.
52
53 ~~~
54 # struct Point {x: f64, y: f64}
55 # fn sqrt(f: f64) -> f64 { 0.0 }
56 fn compute_distance(p1: &Point, p2: &Point) -> f64 {
57     let x_d = p1.x - p2.x;
58     let y_d = p1.y - p2.y;
59     sqrt(x_d * x_d + y_d * y_d)
60 }
61 ~~~
62
63 Now we can call `compute_distance()`:
64
65 ~~~
66 # struct Point {x: f64, y: f64}
67 # let on_the_stack :     Point  =     Point{x: 3.0, y: 4.0};
68 # let on_the_heap  : Box<Point> = box Point{x: 7.0, y: 9.0};
69 # fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
70 compute_distance(&on_the_stack, &*on_the_heap);
71 ~~~
72
73 Here, the `&` operator takes the address of the variable
74 `on_the_stack`; this is because `on_the_stack` has the type `Point`
75 (that is, a struct value) and we have to take its address to get a
76 value. We also call this _borrowing_ the local variable
77 `on_the_stack`, because we have created an alias: that is, another
78 name for the same data.
79
80 Likewise, in the case of `owned_box`,
81 the `&` operator is used in conjunction with the `*` operator
82 to take a reference to the contents of the box.
83
84 Whenever a caller lends data to a callee, there are some limitations on what
85 the caller can do with the original. For example, if the contents of a
86 variable have been lent out, you cannot send that variable to another task. In
87 addition, the compiler will reject any code that might cause the borrowed
88 value to be freed or overwrite its component fields with values of different
89 types (I'll get into what kinds of actions those are shortly). This rule
90 should make intuitive sense: you must wait for a borrower to return the value
91 that you lent it (that is, wait for the reference to go out of scope)
92 before you can make full use of it again.
93
94 # Other uses for the & operator
95
96 In the previous example, the value `on_the_stack` was defined like so:
97
98 ~~~
99 # struct Point {x: f64, y: f64}
100 let on_the_stack: Point = Point {x: 3.0, y: 4.0};
101 ~~~
102
103 This declaration means that code can only pass `Point` by value to other
104 functions. As a consequence, we had to explicitly take the address of
105 `on_the_stack` to get a reference. Sometimes however it is more
106 convenient to move the & operator into the definition of `on_the_stack`:
107
108 ~~~
109 # struct Point {x: f64, y: f64}
110 let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0};
111 ~~~
112
113 Applying `&` to an rvalue (non-assignable location) is just a convenient
114 shorthand for creating a temporary and taking its address. A more verbose
115 way to write the same code is:
116
117 ~~~
118 # struct Point {x: f64, y: f64}
119 let tmp = Point {x: 3.0, y: 4.0};
120 let on_the_stack2 : &Point = &tmp;
121 ~~~
122
123 # Taking the address of fields
124
125 The `&` operator is not limited to taking the address of
126 local variables. It can also take the address of fields or
127 individual array elements. For example, consider this type definition
128 for `Rectangle`:
129
130 ~~~
131 struct Point {x: f64, y: f64} // as before
132 struct Size {w: f64, h: f64} // as before
133 struct Rectangle {origin: Point, size: Size}
134 ~~~
135
136 Now, as before, we can define rectangles in a few different ways:
137
138 ~~~
139 # struct Point {x: f64, y: f64}
140 # struct Size {w: f64, h: f64} // as before
141 # struct Rectangle {origin: Point, size: Size}
142 let rect_stack   =    &Rectangle {origin: Point {x: 1.0, y: 2.0},
143                                   size: Size {w: 3.0, h: 4.0}};
144 let rect_heap    = box Rectangle {origin: Point {x: 5.0, y: 6.0},
145                                   size: Size {w: 3.0, h: 4.0}};
146 ~~~
147
148 In each case, we can extract out individual subcomponents with the `&`
149 operator. For example, I could write:
150
151 ~~~
152 # struct Point {x: f64, y: f64} // as before
153 # struct Size {w: f64, h: f64} // as before
154 # struct Rectangle {origin: Point, size: Size}
155 # let rect_stack  = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}};
156 # let rect_heap   = box Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
157 # fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
158 compute_distance(&rect_stack.origin, &rect_heap.origin);
159 ~~~
160
161 which would borrow the field `origin` from the rectangle on the stack
162 as well as from the owned box, and then compute the distance between them.
163
164 # Lifetimes
165
166 We’ve seen a few examples of borrowing data. To this point, we’ve glossed
167 over issues of safety. As stated in the introduction, at runtime a reference
168 is simply a pointer, nothing more. Therefore, avoiding C's problems with
169 dangling pointers requires a compile-time safety check.
170
171 The basis for the check is the notion of _lifetimes_. A lifetime is a
172 static approximation of the span of execution during which the pointer
173 is valid: it always corresponds to some expression or block within the
174 program.
175
176 The compiler will only allow a borrow *if it can guarantee that the data will
177 not be reassigned or moved for the lifetime of the pointer*. This does not
178 necessarily mean that the data is stored in immutable memory. For example,
179 the following function is legal:
180
181 ~~~
182 # fn some_condition() -> bool { true }
183 # struct Foo { f: int }
184 fn example3() -> int {
185     let mut x = box Foo {f: 3};
186     if some_condition() {
187         let y = &x.f;      // -+ L
188         return *y;         //  |
189     }                      // -+
190     x = box Foo {f: 4};
191     // ...
192 # return 0;
193 }
194 ~~~
195
196 Here, the interior of the variable `x` is being borrowed
197 and `x` is declared as mutable. However, the compiler can prove that
198 `x` is not assigned anywhere in the lifetime L of the variable
199 `y`. Therefore, it accepts the function, even though `x` is mutable
200 and in fact is mutated later in the function.
201
202 It may not be clear why we are so concerned about mutating a borrowed
203 variable. The reason is that the runtime system frees any box
204 _as soon as its owning reference changes or goes out of
205 scope_. Therefore, a program like this is illegal (and would be
206 rejected by the compiler):
207
208 ~~~ {.ignore}
209 fn example3() -> int {
210     let mut x = box X {f: 3};
211     let y = &x.f;
212     x = box X {f: 4};  // Error reported here.
213     *y
214 }
215 ~~~
216
217 To make this clearer, consider this diagram showing the state of
218 memory immediately before the re-assignment of `x`:
219
220 ~~~ {.text}
221     Stack               Exchange Heap
222
223   x +-------------+
224     | box {f:int} | ----+
225   y +-------------+     |
226     | &int        | ----+
227     +-------------+     |    +---------+
228                         +--> |  f: 3   |
229                              +---------+
230 ~~~
231
232 Once the reassignment occurs, the memory will look like this:
233
234 ~~~ {.text}
235     Stack               Exchange Heap
236
237   x +-------------+          +---------+
238     | box {f:int} | -------> |  f: 4   |
239   y +-------------+          +---------+
240     | &int        | ----+
241     +-------------+     |    +---------+
242                         +--> | (freed) |
243                              +---------+
244 ~~~
245
246 Here you can see that the variable `y` still points at the old `f`
247 property of Foo, which has been freed.
248
249 In fact, the compiler can apply the same kind of reasoning to any
250 memory that is (uniquely) owned by the stack frame. So we could
251 modify the previous example to introduce additional owned pointers
252 and structs, and the compiler will still be able to detect possible
253 mutations. This time, we'll use an analogy to illustrate the concept.
254
255 ~~~ {.ignore}
256 fn example3() -> int {
257     struct House { owner: Box<Person> }
258     struct Person { age: int }
259
260     let mut house = box House {
261         owner: box Person {age: 30}
262     };
263
264     let owner_age = &house.owner.age;
265     house = box House {owner: box Person {age: 40}};  // Error reported here.
266     house.owner = box Person {age: 50};               // Error reported here.
267     *owner_age
268 }
269 ~~~
270
271 In this case, two errors are reported, one when the variable `house` is
272 modified and another when `house.owner` is modified. Either modification would
273 invalidate the pointer `owner_age`.
274
275 # Borrowing and enums
276
277 The previous example showed that the type system forbids any mutations
278 of owned boxed values while they are being borrowed. In general, the type
279 system also forbids borrowing a value as mutable if it is already being
280 borrowed - either as a mutable reference or an immutable one. This restriction
281 prevents pointers from pointing into freed memory. There is one other
282 case where the compiler must be very careful to ensure that pointers
283 remain valid: pointers into the interior of an `enum`.
284
285 Let’s look at the following `shape` type that can represent both rectangles
286 and circles:
287
288 ~~~
289 struct Point {x: f64, y: f64}; // as before
290 struct Size {w: f64, h: f64}; // as before
291 enum Shape {
292     Circle(Point, f64),   // origin, radius
293     Rectangle(Point, Size)  // upper-left, dimensions
294 }
295 ~~~
296
297 Now we might write a function to compute the area of a shape. This
298 function takes a reference to a shape, to avoid the need for
299 copying.
300
301 ~~~
302 # struct Point {x: f64, y: f64}; // as before
303 # struct Size {w: f64, h: f64}; // as before
304 # enum Shape {
305 #     Circle(Point, f64),   // origin, radius
306 #     Rectangle(Point, Size)  // upper-left, dimensions
307 # }
308 # static tau: f64 = 6.28;
309 fn compute_area(shape: &Shape) -> f64 {
310     match *shape {
311         Circle(_, radius) => 0.5 * tau * radius * radius,
312         Rectangle(_, ref size) => size.w * size.h
313     }
314 }
315 ~~~
316
317 The first case matches against circles. Here, the pattern extracts the
318 radius from the shape variant and the action uses it to compute the
319 area of the circle. (Like any up-to-date engineer, we use the [tau
320 circle constant][tau] and not that dreadfully outdated notion of pi).
321
322 [tau]: http://www.math.utah.edu/~palais/pi.html
323
324 The second match is more interesting. Here we match against a
325 rectangle and extract its size: but rather than copy the `size`
326 struct, we use a by-reference binding to create a pointer to it. In
327 other words, a pattern binding like `ref size` binds the name `size`
328 to a pointer of type `&size` into the _interior of the enum_.
329
330 To make this more clear, let's look at a diagram of memory layout in
331 the case where `shape` points at a rectangle:
332
333 ~~~ {.text}
334 Stack             Memory
335
336 +-------+         +---------------+
337 | shape | ------> | rectangle(    |
338 +-------+         |   {x: f64,    |
339 | size  | -+      |    y: f64},   |
340 +-------+  +----> |   {w: f64,    |
341                   |    h: f64})   |
342                   +---------------+
343 ~~~
344
345 Here you can see that rectangular shapes are composed of five words of
346 memory. The first is a tag indicating which variant this enum is
347 (`rectangle`, in this case). The next two words are the `x` and `y`
348 fields for the point and the remaining two are the `w` and `h` fields
349 for the size. The binding `size` is then a pointer into the inside of
350 the shape.
351
352 Perhaps you can see where the danger lies: if the shape were somehow
353 to be reassigned, perhaps to a circle, then although the memory used
354 to store that shape value would still be valid, _it would have a
355 different type_! The following diagram shows what memory would look
356 like if code overwrote `shape` with a circle:
357
358 ~~~ {.text}
359 Stack             Memory
360
361 +-------+         +---------------+
362 | shape | ------> | circle(       |
363 +-------+         |   {x: f64,    |
364 | size  | -+      |    y: f64},   |
365 +-------+  +----> |   f64)        |
366                   |               |
367                   +---------------+
368 ~~~
369
370 As you can see, the `size` pointer would be pointing at a `f64`
371 instead of a struct. This is not good: dereferencing the second field
372 of a `f64` as if it were a struct with two fields would be a memory
373 safety violation.
374
375 So, in fact, for every `ref` binding, the compiler will impose the
376 same rules as the ones we saw for borrowing the interior of an owned
377 box: it must be able to guarantee that the `enum` will not be
378 overwritten for the duration of the borrow.  In fact, the compiler
379 would accept the example we gave earlier. The example is safe because
380 the shape pointer has type `&Shape`, which means "reference to
381 immutable memory containing a `shape`". If, however, the type of that
382 pointer were `&mut Shape`, then the ref binding would be ill-typed.
383 Just as with owned boxes, the compiler will permit `ref` bindings
384 into data owned by the stack frame even if the data are mutable,
385 but otherwise it requires that the data reside in immutable memory.
386
387 # Returning references
388
389 So far, all of the examples we have looked at, use references in a
390 “downward” direction. That is, a method or code block creates a
391 reference, then uses it within the same scope. It is also
392 possible to return references as the result of a function, but
393 as we'll see, doing so requires some explicit annotation.
394
395 We could write a subroutine like this:
396
397 ~~~
398 struct Point {x: f64, y: f64}
399 fn get_x<'r>(p: &'r Point) -> &'r f64 { &p.x }
400 ~~~
401
402 Here, the function `get_x()` returns a pointer into the structure it
403 was given. The type of the parameter (`&'r Point`) and return type
404 (`&'r f64`) both use a new syntactic form that we have not seen so
405 far.  Here the identifier `r` names the lifetime of the pointer
406 explicitly. So in effect, this function declares that it takes a
407 pointer with lifetime `r` and returns a pointer with that same
408 lifetime.
409
410 In general, it is only possible to return references if they
411 are derived from a parameter to the procedure. In that case, the
412 pointer result will always have the same lifetime as one of the
413 parameters; named lifetimes indicate which parameter that
414 is.
415
416 In the previous code samples, function parameter types did not include a
417 lifetime name. The compiler simply creates a fresh name for the lifetime
418 automatically: that is, the lifetime name is guaranteed to refer to a distinct
419 lifetime from the lifetimes of all other parameters.
420
421 Named lifetimes that appear in function signatures are conceptually
422 the same as the other lifetimes we have seen before, but they are a bit
423 abstract: they don’t refer to a specific expression within `get_x()`,
424 but rather to some expression within the *caller of `get_x()`*.  The
425 lifetime `r` is actually a kind of *lifetime parameter*: it is defined
426 by the caller to `get_x()`, just as the value for the parameter `p` is
427 defined by that caller.
428
429 In any case, whatever the lifetime of `r` is, the pointer produced by
430 `&p.x` always has the same lifetime as `p` itself: a pointer to a
431 field of a struct is valid as long as the struct is valid. Therefore,
432 the compiler accepts the function `get_x()`.
433
434 To emphasize this point, let’s look at a variation on the example, this
435 time one that does not compile:
436
437 ~~~ {.ignore}
438 struct Point {x: f64, y: f64}
439 fn get_x_sh(p: &Point) -> &f64 {
440     &p.x // Error reported here
441 }
442 ~~~
443
444 Here, the function `get_x_sh()` takes a reference as input and
445 returns a reference. As before, the lifetime of the reference
446 that will be returned is a parameter (specified by the
447 caller). That means that `get_x_sh()` promises to return a reference
448 that is valid for as long as the caller would like: this is
449 subtly different from the first example, which promised to return a
450 pointer that was valid for as long as its pointer argument was valid.
451
452 Within `get_x_sh()`, we see the expression `&p.x` which takes the
453 address of a field of a Point. The presence of this expression
454 implies that the compiler must guarantee that , so long as the
455 resulting pointer is valid, the original Point won't be moved or changed.
456
457 But recall that `get_x_sh()` also promised to
458 return a pointer that was valid for as long as the caller wanted it to
459 be. Clearly, `get_x_sh()` is not in a position to make both of these
460 guarantees; in fact, it cannot guarantee that the pointer will remain
461 valid at all once it returns, as the parameter `p` may or may not be
462 live in the caller. Therefore, the compiler will report an error here.
463
464 In general, if you borrow a struct or box to create a
465 reference, it will only be valid within the function
466 and cannot be returned. This is why the typical way to return references
467 is to take references as input (the only other case in
468 which it can be legal to return a reference is if it
469 points at a static constant).
470
471 # Named lifetimes
472
473 Lifetimes can be named and referenced. For example, the special lifetime
474 `'static`, which does not go out of scope, can be used to create global
475 variables and communicate between tasks (see the manual for use cases).
476
477 ## Parameter Lifetimes
478
479 Named lifetimes allow for grouping of parameters by lifetime.
480 For example, consider this function:
481
482 ~~~
483 # struct Point {x: f64, y: f64}; // as before
484 # struct Size {w: f64, h: f64}; // as before
485 # enum Shape {
486 #     Circle(Point, f64),   // origin, radius
487 #     Rectangle(Point, Size)  // upper-left, dimensions
488 # }
489 # fn compute_area(shape: &Shape) -> f64 { 0.0 }
490 fn select<'r, T>(shape: &'r Shape, threshold: f64,
491                  a: &'r T, b: &'r T) -> &'r T {
492     if compute_area(shape) > threshold {a} else {b}
493 }
494 ~~~
495
496 This function takes three references and assigns each the same
497 lifetime `r`.  In practice, this means that, in the caller, the
498 lifetime `r` will be the *intersection of the lifetime of the three
499 region parameters*. This may be overly conservative, as in this
500 example:
501
502 ~~~
503 # struct Point {x: f64, y: f64}; // as before
504 # struct Size {w: f64, h: f64}; // as before
505 # enum Shape {
506 #     Circle(Point, f64),   // origin, radius
507 #     Rectangle(Point, Size)  // upper-left, dimensions
508 # }
509 # fn compute_area(shape: &Shape) -> f64 { 0.0 }
510 # fn select<'r, T>(shape: &Shape, threshold: f64,
511 #                  a: &'r T, b: &'r T) -> &'r T {
512 #     if compute_area(shape) > threshold {a} else {b}
513 # }
514                                                      // -+ r
515 fn select_based_on_unit_circle<'r, T>(               //  |-+ B
516     threshold: f64, a: &'r T, b: &'r T) -> &'r T {   //  | |
517                                                      //  | |
518     let shape = Circle(Point {x: 0., y: 0.}, 1.);    //  | |
519     select(&shape, threshold, a, b)                  //  | |
520 }                                                    //  |-+
521                                                      // -+
522 ~~~
523
524 In this call to `select()`, the lifetime of the first parameter shape
525 is B, the function body. Both of the second two parameters `a` and `b`
526 share the same lifetime, `r`, which is a lifetime parameter of
527 `select_based_on_unit_circle()`. The caller will infer the
528 intersection of these two lifetimes as the lifetime of the returned
529 value, and hence the return value of `select()` will be assigned a
530 lifetime of B. This will in turn lead to a compilation error, because
531 `select_based_on_unit_circle()` is supposed to return a value with the
532 lifetime `r`.
533
534 To address this, we can modify the definition of `select()` to
535 distinguish the lifetime of the first parameter from the lifetime of
536 the latter two. After all, the first parameter is not being
537 returned. Here is how the new `select()` might look:
538
539 ~~~
540 # struct Point {x: f64, y: f64}; // as before
541 # struct Size {w: f64, h: f64}; // as before
542 # enum Shape {
543 #     Circle(Point, f64),   // origin, radius
544 #     Rectangle(Point, Size)  // upper-left, dimensions
545 # }
546 # fn compute_area(shape: &Shape) -> f64 { 0.0 }
547 fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: f64,
548                        a: &'r T, b: &'r T) -> &'r T {
549     if compute_area(shape) > threshold {a} else {b}
550 }
551 ~~~
552
553 Here you can see that `shape`'s lifetime is now named `tmp`. The
554 parameters `a`, `b`, and the return value all have the lifetime `r`.
555 However, since the lifetime `tmp` is not returned, it would be more
556 concise to just omit the named lifetime for `shape` altogether:
557
558 ~~~
559 # struct Point {x: f64, y: f64}; // as before
560 # struct Size {w: f64, h: f64}; // as before
561 # enum Shape {
562 #     Circle(Point, f64),   // origin, radius
563 #     Rectangle(Point, Size)  // upper-left, dimensions
564 # }
565 # fn compute_area(shape: &Shape) -> f64 { 0.0 }
566 fn select<'r, T>(shape: &Shape, threshold: f64,
567                  a: &'r T, b: &'r T) -> &'r T {
568     if compute_area(shape) > threshold {a} else {b}
569 }
570 ~~~
571
572 This is equivalent to the previous definition.
573
574 ## Labeled Control Structures
575
576 Named lifetime notation can also be used to control the flow of execution:
577
578 ~~~
579 'h: for i in range(0u, 10) {
580     'g: loop {
581         if i % 2 == 0 { continue 'h; }
582         if i == 9 { break 'h; }
583         break 'g;
584     }
585 }
586 ~~~
587
588 > *Note:* Labelled breaks are not currently supported within `while` loops.
589
590 Named labels are hygienic and can be used safely within macros.
591 See the macros guide section on hygiene for more details.
592
593 # Conclusion
594
595 So there you have it: a (relatively) brief tour of the lifetime
596 system. For more details, we refer to the (yet to be written) reference
597 document on references, which will explain the full notation
598 and give more examples.