]> git.proxmox.com Git - rustc.git/blob - src/doc/nomicon/src/lifetimes.md
New upstream version 1.36.0+dfsg1
[rustc.git] / src / doc / nomicon / src / lifetimes.md
1 # Lifetimes
2
3 Rust enforces these rules through *lifetimes*. Lifetimes are named
4 regions of code that a reference must be valid for. Those regions
5 may be fairly complex, as they correspond to paths of execution
6 in the program. There may even be holes in these paths of execution,
7 as it's possible to invalidate a reference as long as it's reinitialized
8 before it's used again. Types which contain references (or pretend to)
9 may also be tagged with lifetimes so that Rust can prevent them from
10 being invalidated as well.
11
12 In most of our examples, the lifetimes will coincide with scopes. This is
13 because our examples are simple. The more complex cases where they don't
14 coincide are described below.
15
16 Within a function body, Rust generally doesn't let you explicitly name the
17 lifetimes involved. This is because it's generally not really necessary
18 to talk about lifetimes in a local context; Rust has all the information and
19 can work out everything as optimally as possible. Many anonymous scopes and
20 temporaries that you would otherwise have to write are often introduced to
21 make your code Just Work.
22
23 However once you cross the function boundary, you need to start talking about
24 lifetimes. Lifetimes are denoted with an apostrophe: `'a`, `'static`. To dip
25 our toes with lifetimes, we're going to pretend that we're actually allowed
26 to label scopes with lifetimes, and desugar the examples from the start of
27 this chapter.
28
29 Originally, our examples made use of *aggressive* sugar -- high fructose corn
30 syrup even -- around scopes and lifetimes, because writing everything out
31 explicitly is *extremely noisy*. All Rust code relies on aggressive inference
32 and elision of "obvious" things.
33
34 One particularly interesting piece of sugar is that each `let` statement
35 implicitly introduces a scope. For the most part, this doesn't really matter.
36 However it does matter for variables that refer to each other. As a simple
37 example, let's completely desugar this simple piece of Rust code:
38
39 ```rust
40 let x = 0;
41 let y = &x;
42 let z = &y;
43 ```
44
45 The borrow checker always tries to minimize the extent of a lifetime, so it will
46 likely desugar to the following:
47
48 ```rust,ignore
49 // NOTE: `'a: {` and `&'b x` is not valid syntax!
50 'a: {
51 let x: i32 = 0;
52 'b: {
53 // lifetime used is 'b because that's good enough.
54 let y: &'b i32 = &'b x;
55 'c: {
56 // ditto on 'c
57 let z: &'c &'b i32 = &'c y;
58 }
59 }
60 }
61 ```
62
63 Wow. That's... awful. Let's all take a moment to thank Rust for making this easier.
64
65 Actually passing references to outer scopes will cause Rust to infer
66 a larger lifetime:
67
68 ```rust
69 let x = 0;
70 let z;
71 let y = &x;
72 z = y;
73 ```
74
75 ```rust,ignore
76 'a: {
77 let x: i32 = 0;
78 'b: {
79 let z: &'b i32;
80 'c: {
81 // Must use 'b here because this reference is
82 // being passed to that scope.
83 let y: &'b i32 = &'b x;
84 z = y;
85 }
86 }
87 }
88 ```
89
90
91
92 # Example: references that outlive referents
93
94 Alright, let's look at some of those examples from before:
95
96 ```rust,compile_fail
97 fn as_str(data: &u32) -> &str {
98 let s = format!("{}", data);
99 &s
100 }
101 ```
102
103 desugars to:
104
105 ```rust,ignore
106 fn as_str<'a>(data: &'a u32) -> &'a str {
107 'b: {
108 let s = format!("{}", data);
109 return &'a s;
110 }
111 }
112 ```
113
114 This signature of `as_str` takes a reference to a u32 with *some* lifetime, and
115 promises that it can produce a reference to a str that can live *just as long*.
116 Already we can see why this signature might be trouble. That basically implies
117 that we're going to find a str somewhere in the scope the reference
118 to the u32 originated in, or somewhere *even earlier*. That's a bit of a tall
119 order.
120
121 We then proceed to compute the string `s`, and return a reference to it. Since
122 the contract of our function says the reference must outlive `'a`, that's the
123 lifetime we infer for the reference. Unfortunately, `s` was defined in the
124 scope `'b`, so the only way this is sound is if `'b` contains `'a` -- which is
125 clearly false since `'a` must contain the function call itself. We have therefore
126 created a reference whose lifetime outlives its referent, which is *literally*
127 the first thing we said that references can't do. The compiler rightfully blows
128 up in our face.
129
130 To make this more clear, we can expand the example:
131
132 ```rust,ignore
133 fn as_str<'a>(data: &'a u32) -> &'a str {
134 'b: {
135 let s = format!("{}", data);
136 return &'a s
137 }
138 }
139
140 fn main() {
141 'c: {
142 let x: u32 = 0;
143 'd: {
144 // An anonymous scope is introduced because the borrow does not
145 // need to last for the whole scope x is valid for. The return
146 // of as_str must find a str somewhere before this function
147 // call. Obviously not happening.
148 println!("{}", as_str::<'d>(&'d x));
149 }
150 }
151 }
152 ```
153
154 Shoot!
155
156 Of course, the right way to write this function is as follows:
157
158 ```rust
159 fn to_string(data: &u32) -> String {
160 format!("{}", data)
161 }
162 ```
163
164 We must produce an owned value inside the function to return it! The only way
165 we could have returned an `&'a str` would have been if it was in a field of the
166 `&'a u32`, which is obviously not the case.
167
168 (Actually we could have also just returned a string literal, which as a global
169 can be considered to reside at the bottom of the stack; though this limits
170 our implementation *just a bit*.)
171
172
173
174
175
176 # Example: aliasing a mutable reference
177
178 How about the other example:
179
180 ```rust,compile_fail
181 let mut data = vec![1, 2, 3];
182 let x = &data[0];
183 data.push(4);
184 println!("{}", x);
185 ```
186
187 ```rust,ignore
188 'a: {
189 let mut data: Vec<i32> = vec![1, 2, 3];
190 'b: {
191 // 'b is as big as we need this borrow to be
192 // (just need to get to `println!`)
193 let x: &'b i32 = Index::index::<'b>(&'b data, 0);
194 'c: {
195 // Temporary scope because we don't need the
196 // &mut to last any longer.
197 Vec::push(&'c mut data, 4);
198 }
199 println!("{}", x);
200 }
201 }
202 ```
203
204 The problem here is a bit more subtle and interesting. We want Rust to
205 reject this program for the following reason: We have a live shared reference `x`
206 to a descendant of `data` when we try to take a mutable reference to `data`
207 to `push`. This would create an aliased mutable reference, which would
208 violate the *second* rule of references.
209
210 However this is *not at all* how Rust reasons that this program is bad. Rust
211 doesn't understand that `x` is a reference to a subpath of `data`. It doesn't
212 understand `Vec` at all. What it *does* see is that `x` has to live for `'b` to
213 be printed. The signature of `Index::index` subsequently demands that the
214 reference we take to `data` has to survive for `'b`. When we try to call `push`,
215 it then sees us try to make an `&'c mut data`. Rust knows that `'c` is contained
216 within `'b`, and rejects our program because the `&'b data` must still be live!
217
218 Here we see that the lifetime system is much more coarse than the reference
219 semantics we're actually interested in preserving. For the most part, *that's
220 totally ok*, because it keeps us from spending all day explaining our program
221 to the compiler. However it does mean that several programs that are totally
222 correct with respect to Rust's *true* semantics are rejected because lifetimes
223 are too dumb.
224
225
226
227 # The area covered by a lifetime
228
229 The lifetime (sometimes called a *borrow*) is *alive* from the place it is
230 created to its last use. The borrowed thing needs to outlive only borrows that
231 are alive. This looks simple, but there are few subtleties.
232
233 The following snippet compiles, because after printing `x`, it is no longer
234 needed, so it doesn't matter if it is dangling or aliased (even though the
235 variable `x` *technically* exists to the very end of the scope).
236
237 ```rust,edition2018
238 let mut data = vec![1, 2, 3];
239 let x = &data[0];
240 println!("{}", x);
241 // This is OK, x is no longer needed
242 data.push(4);
243 ```
244
245 However, if the value has a destructor, the destructor is run at the end of the
246 scope. And running the destructor is considered a use ‒ obviously the last one.
247 So, this will *not* compile.
248
249 ```rust,edition2018,compile_fail
250 #[derive(Debug)]
251 struct X<'a>(&'a i32);
252
253 impl Drop for X<'_> {
254 fn drop(&mut self) {}
255 }
256
257 let mut data = vec![1, 2, 3];
258 let x = X(&data[0]);
259 println!("{:?}", x);
260 data.push(4);
261 // Here, the destructor is run and therefore this'll fail to compile.
262 ```
263
264 Furthermore, there might be multiple possible last uses of the borrow, for
265 example in each branch of a condition.
266
267 ```rust,edition2018
268 # fn some_condition() -> bool { true }
269 let mut data = vec![1, 2, 3];
270 let x = &data[0];
271
272 if some_condition() {
273 println!("{}", x); // This is the last use of `x` in this branch
274 data.push(4); // So we can push here
275 } else {
276 // There's no use of `x` in here, so effectively the last use is the
277 // creation of x at the top of the example.
278 data.push(5);
279 }
280 ```
281
282 And a lifetime can have a pause in it. Or you might look at it as two distinct
283 borrows just being tied to the same local variable. This often happens around
284 loops (writing a new value of a variable at the end of the loop and using it for
285 the last time at the top of the next iteration).
286
287 ```rust,edition2018
288 let mut data = vec![1, 2, 3];
289 // This mut allows us to change where the reference points to
290 let mut x = &data[0];
291
292 println!("{}", x); // Last use of this borrow
293 data.push(4);
294 x = &data[3]; // We start a new borrow here
295 println!("{}", x);
296 ```
297
298 Historically, Rust kept the borrow alive until the end of scope, so these
299 examples might fail to compile with older compilers. Also, there are still some
300 corner cases where Rust fails to properly shorten the live part of the borrow
301 and fails to compile even when it looks like it should. These'll be solved over
302 time.