1
1
# Unbounded Lifetimes
2
2
3
3
Unsafe code can often end up producing references or lifetimes out of thin air.
4
- Such lifetimes come into the world as * unbounded* . The most common source of this
5
- is dereferencing a raw pointer, which produces a reference with an unbounded lifetime.
6
- Such a lifetime becomes as big as context demands. This is in fact more powerful
7
- than simply becoming ` 'static ` , because for instance ` &'static &'a T `
8
- will fail to typecheck, but the unbound lifetime will perfectly mold into
9
- ` &'a &'a T ` as needed. However for most intents and purposes, such an unbounded
10
- lifetime can be regarded as ` 'static ` .
4
+ Such lifetimes come into the world as * unbounded* . The most common source of
5
+ this is taking a reference to a dereferenced raw pointer, which produces a
6
+ reference with an unbounded lifetime. Such a lifetime becomes as big as context
7
+ demands. This is in fact more powerful than simply becoming ` 'static ` , because
8
+ for instance ` &'static &'a T ` will fail to typecheck, but the unbound lifetime
9
+ will perfectly mold into ` &'a &'a T ` as needed. However for most intents and
10
+ purposes, such an unbounded lifetime can be regarded as ` 'static ` .
11
11
12
12
Almost no reference is ` 'static ` , so this is probably wrong. ` transmute ` and
13
13
` transmute_copy ` are the two other primary offenders. One should endeavor to
@@ -17,17 +17,25 @@ boundaries.
17
17
Given a function, any output lifetimes that don't derive from inputs are
18
18
unbounded. For instance:
19
19
20
- <!-- ignore: simplified code -->
21
- ``` rust,ignore
22
- fn get_str<'a>() -> &'a str;
20
+ <!-- no_run: This example exhibits undefined behavior. -->
21
+ ``` rust,no_run
22
+ fn get_str<'a>(s: *const String) -> &'a str {
23
+ unsafe { &*s }
24
+ }
25
+
26
+ fn main() {
27
+ let soon_dropped = String::from("hello");
28
+ let dangling = get_str(&soon_dropped);
29
+ drop(soon_dropped);
30
+ println!("Invalid str: {}", dangling); // Invalid str: gӚ_`
31
+ }
23
32
```
24
33
25
- will produce an ` &str ` with an unbounded lifetime. The easiest way to avoid
26
- unbounded lifetimes is to use lifetime elision at the function boundary.
27
- If an output lifetime is elided, then it * must* be bounded by an input lifetime.
28
- Of course it might be bounded by the * wrong* lifetime, but this will usually
29
- just cause a compiler error, rather than allow memory safety to be trivially
30
- violated.
34
+ The easiest way to avoid unbounded lifetimes is to use lifetime elision at the
35
+ function boundary. If an output lifetime is elided, then it * must* be bounded by
36
+ an input lifetime. Of course it might be bounded by the * wrong* lifetime, but
37
+ this will usually just cause a compiler error, rather than allow memory safety
38
+ to be trivially violated.
31
39
32
40
Within a function, bounding lifetimes is more error-prone. The safest and easiest
33
41
way to bound a lifetime is to return it from a function with a bound lifetime.
0 commit comments