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