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,24 @@ 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
+ ``` rust
21
+ fn get_str <'a >(s : * const String ) -> & 'a str {
22
+ unsafe { & * s }
23
+ }
24
+
25
+ fn main () {
26
+ let soon_dropped = String :: from (" hello" );
27
+ let dangling = get_str (& soon_dropped );
28
+ drop (soon_dropped );
29
+ println! (" Invalid str: {}" , dangling ); // Invalid str: gӚ_`
30
+ }
23
31
```
24
32
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.
33
+ The easiest way to avoid unbounded lifetimes is to use lifetime elision at the
34
+ function boundary. If an output lifetime is elided, then it * must* be bounded by
35
+ an input lifetime. Of course it might be bounded by the * wrong* lifetime, but
36
+ this will usually just cause a compiler error, rather than allow memory safety
37
+ to be trivially violated.
31
38
32
39
Within a function, bounding lifetimes is more error-prone. The safest and easiest
33
40
way to bound a lifetime is to return it from a function with a bound lifetime.
0 commit comments