Skip to content

Commit

Permalink
Merge pull request #1320 from najamelan/rewrite/static
Browse files Browse the repository at this point in the history
Rewrite section on 'static lifetime.
  • Loading branch information
marioidival authored Mar 29, 2020
2 parents f283b50 + bef6311 commit 6030fcb
Showing 1 changed file with 69 additions and 9 deletions.
78 changes: 69 additions & 9 deletions src/scope/lifetime/static_lifetime.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
# Static

A `'static` lifetime is the longest possible lifetime, and lasts for
the lifetime of the running program. A `'static` lifetime may also be
coerced to a shorter lifetime. There are two ways to make a variable
with `'static` lifetime, and both are stored in the read-only memory
of the binary:
Rust has a few reserved lifetime names. One of those is `'static`. You
might encounter it in two situations:

```rust, editable
// A reference with 'static lifetime:
let s: &'static str = "hello world";
// 'static as part of a trait bound:
fn generic<T>(x: T) where T: 'static {}
```

Both are related but subtly different and this is a common source for
confusion when learning Rust. Here are some examples for each situation:

## Reference lifetime

As a reference lifetime `'static` indicates that the data pointed to by
the reference lives for the entire lifetime of the running program.
It can still be coerced to a shorter lifetime.

There are two ways to make a variable with `'static` lifetime, and both
are stored in the read-only memory of the binary:

* Make a constant with the `static` declaration.
* Make a `string` literal which has type: `&'static str`.
Expand All @@ -15,7 +32,7 @@ See the following example for a display of each method:
// Make a constant with `'static` lifetime.
static NUM: i32 = 18;
// Returns a reference to `NUM` where its `'static`
// Returns a reference to `NUM` where its `'static`
// lifetime is coerced to that of the input argument.
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
&NUM
Expand All @@ -30,7 +47,7 @@ fn main() {
// When `static_string` goes out of scope, the reference
// can no longer be used, but the data remains in the binary.
}
{
// Make an integer to use for `coerce_static`:
let lifetime_num = 9;
Expand All @@ -40,13 +57,56 @@ fn main() {
println!("coerced_static: {}", coerced_static);
}
println!("NUM: {} stays accessible!", NUM);
}
```

## Trait bound

As a trait bound, it means the type does not contain any non-static
references. Eg. the receiver can hold on to the type for as long as
they want and it will never become invalid until they drop it.

It's important to understand this means that any owned data always passes
a `'static` lifetime bound, but a reference to that owned data generally
does not:

```rust,editable,compile_fail
use std::fmt::Debug;
fn print_it( input: impl Debug + 'static )
{
println!( "'static value passed in is: {:?}", input );
}
fn use_it()
{
// i is owned and contains no references, thus it's 'static:
let i = 5;
print_it(i);
// oops, &i only has the lifetime defined by the scope of
// use_it(), so it's not 'static:
print_it(&i);
}
```
The compiler will tell you:
```ignore
error[E0597]: `i` does not live long enough
--> src/lib.rs:15:15
|
15 | print_it(&i);
| ---------^^--
| | |
| | borrowed value does not live long enough
| argument requires that `i` is borrowed for `'static`
16 | }
| - `i` dropped here while still borrowed
```

### See also:

[`'static` constants][static_const]

[static_const]: ../../custom_types/constants.md
[static_const]: ../../custom_types/constants.md

0 comments on commit 6030fcb

Please sign in to comment.