Skip to content

Commit 0cf9aae

Browse files
committed
Rewrite section on 'static lifetime.
This tries to be more precise and in specific help avoid confusion about 'static trait bounds.
1 parent c49ae9e commit 0cf9aae

File tree

1 file changed

+69
-9
lines changed

1 file changed

+69
-9
lines changed

src/scope/lifetime/static_lifetime.md

+69-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
# Static
22

3-
A `'static` lifetime is the longest possible lifetime, and lasts for
4-
the lifetime of the running program. A `'static` lifetime may also be
5-
coerced to a shorter lifetime. There are two ways to make a variable
6-
with `'static` lifetime, and both are stored in the read-only memory
7-
of the binary:
3+
Rust has a few reserved lifetime names. One of those is `'static`. You
4+
might encounter it in two situations:
5+
6+
```rust, editable
7+
// A reference with 'static lifetime
8+
let s: &'static str = "hello world";
9+
10+
// 'static as part of a trait bound.
11+
fn generic<T>(x: T) where T: 'static {}
12+
```
13+
14+
Both are related but subtly different and this is a common source for
15+
confusion when learning Rust. Here are some examples for each situation:
16+
17+
## Reference lifetime
18+
19+
As a reference lifetime `'static` indicates that the data pointed to by
20+
the reference lives for the entire lifetime of the running program.
21+
It can still be coerced to a shorter lifetime.
22+
23+
There are two ways to make a variable with `'static` lifetime, and both
24+
are stored in the read-only memory of the binary:
825

926
* Make a constant with the `static` declaration.
1027
* Make a `string` literal which has type: `&'static str`.
@@ -15,7 +32,7 @@ See the following example for a display of each method:
1532
// Make a constant with `'static` lifetime.
1633
static NUM: i32 = 18;
1734
18-
// Returns a reference to `NUM` where its `'static`
35+
// Returns a reference to `NUM` where its `'static`
1936
// lifetime is coerced to that of the input argument.
2037
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
2138
&NUM
@@ -30,7 +47,7 @@ fn main() {
3047
// When `static_string` goes out of scope, the reference
3148
// can no longer be used, but the data remains in the binary.
3249
}
33-
50+
3451
{
3552
// Make an integer to use for `coerce_static`:
3653
let lifetime_num = 9;
@@ -40,13 +57,56 @@ fn main() {
4057
4158
println!("coerced_static: {}", coerced_static);
4259
}
43-
60+
4461
println!("NUM: {} stays accessible!", NUM);
4562
}
4663
```
4764

65+
## Trait bound
66+
67+
As a trait bound, it means the type does not contain any non-static
68+
references. Eg. the receiver can hold on to the type for as long as
69+
they want and it will never become invalid until they drop it.
70+
71+
It's important to understand this means that any owned data always passes
72+
a `'static` lifetime bound, but a reference to that owned data generally
73+
does not:
74+
75+
```rust,editable,compile_fail
76+
use std::fmt::Debug;
77+
78+
fn print_it( input: impl Debug + 'static )
79+
{
80+
println!( "'static value passed in is: {:?}", input );
81+
}
82+
83+
fn use_it()
84+
{
85+
// i is owned and contains no references, thus it's 'static:
86+
let i = 5;
87+
print_it(i);
88+
89+
// oops, &i only has the lifetime defined by the scope of
90+
// use_it(), so it's not 'static:
91+
print_it(&i);
92+
}
93+
```
94+
The compiler will tell you:
95+
```ignore
96+
error[E0597]: `i` does not live long enough
97+
--> src/lib.rs:15:15
98+
|
99+
15 | print_it(&i);
100+
| ---------^^--
101+
| | |
102+
| | borrowed value does not live long enough
103+
| argument requires that `i` is borrowed for `'static`
104+
16 | }
105+
| - `i` dropped here while still borrowed
106+
```
107+
48108
### See also:
49109

50110
[`'static` constants][static_const]
51111

52-
[static_const]: ../../custom_types/constants.md
112+
[static_const]: ../../custom_types/constants.md

0 commit comments

Comments
 (0)