]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/lifetimes.md
Rollup merge of #25614 - parir:patch-2, r=alexcrichton
[rust.git] / src / doc / trpl / lifetimes.md
1 % Lifetimes
2
3 This guide is one of three presenting Rust’s ownership system. This is one of
4 Rust’s most unique and compelling features, with which Rust developers should
5 become quite acquainted. Ownership is how Rust achieves its largest goal,
6 memory safety. There are a few distinct concepts, each with its own chapter:
7
8 * [ownership][ownership], the key concept
9 * [borrowing][borrowing], and their associated feature ‘references’
10 * lifetimes, which you’re reading now
11
12 These three chapters are related, and in order. You’ll need all three to fully
13 understand the ownership system.
14
15 [ownership]: ownership.html
16 [borrowing]: references-and-borrowing.html
17
18 # Meta
19
20 Before we get to the details, two important notes about the ownership system.
21
22 Rust has a focus on safety and speed. It accomplishes these goals through many
23 ‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
24 as possible in order to make them work. The ownership system is a prime example
25 of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
26 is _done at compile time_. You do not pay any run-time cost for any of these
27 features.
28
29 However, this system does have a certain cost: learning curve. Many new users
30 to Rust experience something we like to call ‘fighting with the borrow
31 checker’, where the Rust compiler refuses to compile a program that the author
32 thinks is valid. This often happens because the programmer’s mental model of
33 how ownership should work doesn’t match the actual rules that Rust implements.
34 You probably will experience similar things at first. There is good news,
35 however: more experienced Rust developers report that once they work with the
36 rules of the ownership system for a period of time, they fight the borrow
37 checker less and less.
38
39 With that in mind, let’s learn about lifetimes.
40
41 # Lifetimes
42
43 Lending out a reference to a resource that someone else owns can be
44 complicated. For example, imagine this set of operations:
45
46 - I acquire a handle to some kind of resource.
47 - I lend you a reference to the resource.
48 - I decide I’m done with the resource, and deallocate it, while you still have
49   your reference.
50 - You decide to use the resource.
51
52 Uh oh! Your reference is pointing to an invalid resource. This is called a
53 dangling pointer or ‘use after free’, when the resource is memory.
54
55 To fix this, we have to make sure that step four never happens after step
56 three. The ownership system in Rust does this through a concept called
57 lifetimes, which describe the scope that a reference is valid for.
58
59 When we have a function that takes a reference by argument, we can be implicit
60 or explicit about the lifetime of the reference:
61
62 ```rust
63 // implicit
64 fn foo(x: &i32) {
65 }
66
67 // explicit
68 fn bar<'a>(x: &'a i32) {
69 }
70 ```
71
72 The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime
73 associated with it, but the compiler lets you elide them in common cases.
74 Before we get to that, though, let’s break the explicit example down:
75
76 ```rust,ignore
77 fn bar<'a>(...)
78 ```
79
80 This part declares our lifetimes. This says that `bar` has one lifetime, `'a`.
81 If we had two reference parameters, it would look like this:
82
83 ```rust,ignore
84 fn bar<'a, 'b>(...)
85 ```
86
87 Then in our parameter list, we use the lifetimes we’ve named:
88
89 ```rust,ignore
90 ...(x: &'a i32)
91 ```
92
93 If we wanted an `&mut` reference, we’d do this:
94
95 ```rust,ignore
96 ...(x: &'a mut i32)
97 ```
98
99 If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s just that
100 the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
101 i32` as ‘a mutable reference to an i32’ and `&'a mut i32` as ‘a mutable
102 reference to an `i32` with the lifetime `'a`’.
103
104 You’ll also need explicit lifetimes when working with [`struct`][structs]s:
105
106 ```rust
107 struct Foo<'a> {
108     x: &'a i32,
109 }
110
111 fn main() {
112     let y = &5; // this is the same as `let _y = 5; let y = &_y;`
113     let f = Foo { x: y };
114
115     println!("{}", f.x);
116 }
117 ```
118
119 [structs]: structs.html
120
121 As you can see, `struct`s can also have lifetimes. In a similar way to functions,
122
123 ```rust
124 struct Foo<'a> {
125 # x: &'a i32,
126 # }
127 ```
128
129 declares a lifetime, and
130
131 ```rust
132 # struct Foo<'a> {
133 x: &'a i32,
134 # }
135 ```
136
137 uses it. So why do we need a lifetime here? We need to ensure that any reference
138 to a `Foo` cannot outlive the reference to an `i32` it contains.
139
140 ## Thinking in scopes
141
142 A way to think about lifetimes is to visualize the scope that a reference is
143 valid for. For example:
144
145 ```rust
146 fn main() {
147     let y = &5;     // -+ y goes into scope
148                     //  |
149     // stuff        //  |
150                     //  |
151 }                   // -+ y goes out of scope
152 ```
153
154 Adding in our `Foo`:
155
156 ```rust
157 struct Foo<'a> {
158     x: &'a i32,
159 }
160
161 fn main() {
162     let y = &5;           // -+ y goes into scope
163     let f = Foo { x: y }; // -+ f goes into scope
164     // stuff              //  |
165                           //  |
166 }                         // -+ f and y go out of scope
167 ```
168
169 Our `f` lives within the scope of `y`, so everything works. What if it didn’t?
170 This code won’t work:
171
172 ```rust,ignore
173 struct Foo<'a> {
174     x: &'a i32,
175 }
176
177 fn main() {
178     let x;                    // -+ x goes into scope
179                               //  |
180     {                         //  |
181         let y = &5;           // ---+ y goes into scope
182         let f = Foo { x: y }; // ---+ f goes into scope
183         x = &f.x;             //  | | error here
184     }                         // ---+ f and y go out of scope
185                               //  |
186     println!("{}", x);        //  |
187 }                             // -+ x goes out of scope
188 ```
189
190 Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope
191 of `x`. But when we do `x = &f.x`, we make `x` a reference to something that’s
192 about to go out of scope.
193
194 Named lifetimes are a way of giving these scopes a name. Giving something a
195 name is the first step towards being able to talk about it.
196
197 ## 'static
198
199 The lifetime named ‘static’ is a special lifetime. It signals that something
200 has the lifetime of the entire program. Most Rust programmers first come across
201 `'static` when dealing with strings:
202
203 ```rust
204 let x: &'static str = "Hello, world.";
205 ```
206
207 String literals have the type `&'static str` because the reference is always
208 alive: they are baked into the data segment of the final binary. Another
209 example are globals:
210
211 ```rust
212 static FOO: i32 = 5;
213 let x: &'static i32 = &FOO;
214 ```
215
216 This adds an `i32` to the data segment of the binary, and `x` is a reference
217 to it.
218
219 ## Lifetime Elision
220
221 Rust supports powerful local type inference in function bodies, but it’s
222 forbidden in item signatures to allow reasoning about the types based on
223 the item signature alone. However, for ergonomic reasons a very restricted
224 secondary inference algorithm called “lifetime elision” applies in function
225 signatures. It infers only based on the signature components themselves and not
226 based on the body of the function, only infers lifetime parameters, and does
227 this with only three easily memorizable and unambiguous rules. This makes
228 lifetime elision a shorthand for writing an item signature, while not hiding
229 away the actual types involved as full local inference would if applied to it.
230
231 When talking about lifetime elision, we use the term *input lifetime* and
232 *output lifetime*. An *input lifetime* is a lifetime associated with a parameter
233 of a function, and an *output lifetime* is a lifetime associated with the return
234 value of a function. For example, this function has an input lifetime:
235
236 ```rust,ignore
237 fn foo<'a>(bar: &'a str)
238 ```
239
240 This one has an output lifetime:
241
242 ```rust,ignore
243 fn foo<'a>() -> &'a str
244 ```
245
246 This one has a lifetime in both positions:
247
248 ```rust,ignore
249 fn foo<'a>(bar: &'a str) -> &'a str
250 ```
251
252 Here are the three rules:
253
254 * Each elided lifetime in a function’s arguments becomes a distinct lifetime
255   parameter.
256
257 * If there is exactly one input lifetime, elided or not, that lifetime is
258   assigned to all elided lifetimes in the return values of that function.
259
260 * If there are multiple input lifetimes, but one of them is `&self` or `&mut
261   self`, the lifetime of `self` is assigned to all elided output lifetimes.
262
263 Otherwise, it is an error to elide an output lifetime.
264
265 ### Examples
266
267 Here are some examples of functions with elided lifetimes.  We’ve paired each
268 example of an elided lifetime with its expanded form.
269
270 ```rust,ignore
271 fn print(s: &str); // elided
272 fn print<'a>(s: &'a str); // expanded
273
274 fn debug(lvl: u32, s: &str); // elided
275 fn debug<'a>(lvl: u32, s: &'a str); // expanded
276
277 // In the preceding example, `lvl` doesn’t need a lifetime because it’s not a
278 // reference (`&`). Only things relating to references (such as a `struct`
279 // which contains a reference) need lifetimes.
280
281 fn substr(s: &str, until: u32) -> &str; // elided
282 fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
283
284 fn get_str() -> &str; // ILLEGAL, no inputs
285
286 fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
287 fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is unclear
288
289 fn get_mut(&mut self) -> &mut T; // elided
290 fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
291
292 fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
293 fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
294
295 fn new(buf: &mut [u8]) -> BufWriter; // elided
296 fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
297 ```