Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fight the confusion over 'static #1316

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 53 additions & 7 deletions src/scope/lifetime/static_lifetime.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
# 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:
`'static` is one of the reserved lifetime specifiers. It has a special meaning
in Rust. A __reference__ that has a `'static` lifetime is guaranteed to be
valid for the entire lifetime of the running program.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not quite correct. It may live for the entire lifetime, but does not have to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that if I had an API that takes in a &'static Something it would possibly stop being valid at some point before the end of the program? That seems problematic, no? How do you know when?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@najamelan najamelan Mar 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but now we are confusing with the lifetime of the variable binding of the reference. I generally assumed that when we speak about reference lifetimes, we mean the lifetime of the pointed to data and the one we name as in &'a SomeValue -> 'a in this case. The text says "the reference is guaranteed to be valid", as opposed to "The reference lives for ...". Of course you are allowed to drop it sooner if you don't need it anymore. Given that beginners will most often read the book, this is probably a bad assumption on my part.

But if you feel that that is still not clear enough, I will propose a complete rewrite. I am generally in favor of being very precise and thorough, but often my documentation PR's get downplayed, so I didn't necessarily proposed the way I like it best but more as what I estimate the general opinion might be. It will probably be a fair bit longer if trying to be complete. I suppose also that in RBE we prefer showing code rather than long descriptions?


There are two ways to create data that lives for the entire lifetime of
a program and both are stored in the read-only memory of the binary:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also not the only two ways: owned values are 'static.

Copy link
Contributor Author

@najamelan najamelan Mar 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two points where there in the original text. The PR tries to make the distinction between 'static as a bound, which passes for owned data, and 'static on a reference. That's the whole point of a common confusion. Owned data AFAICT won't live for the entire lifetime of the program unless it is in a global. Otherwise it's always scoped, maybe to fn main() but still scoped.

I don't know if you are just reading the diff, it might be worth to zoom out and read both versions in their entirety.


* Make a constant with the `static` declaration.
* Make a `string` literal which has type: `&'static str`.

See the following example for a display of each method:
__Warning__: It's easy to get confused about `'static` because all variable
bindings that own their data, eg. do not contain references, fulfill a
bound on `'static`:

```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()
{
let i = 5; // i is owned and contains no references, thus it's 'static
print_it( i ); // valid call

// 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
```

A bound on `'static` means that the callee does not have to worry
about their variable binding becoming invalid after some time.
They can use it as long as they want. In contrast to a `'static`
__reference__, this is unrelated to the runtime of the entire program.

A `'static` lifetime may also be coerced to a shorter lifetime.

See the following example for uses of `'static`:

```rust,editable
// Make a constant with `'static` lifetime.
Expand Down Expand Up @@ -49,4 +95,4 @@ fn main() {

[`'static` constants][static_const]

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