1. 1. Introduction
  2. 2. Meet Safe and Unsafe
    1. 2.1. How Safe and Unsafe Interact
    2. 2.2. Working with Unsafe
  3. 3. Data Layout
    1. 3.1. repr(Rust)
    2. 3.2. Exotically Sized Types
    3. 3.3. Other reprs
  4. 4. Ownership
    1. 4.1. References
    2. 4.2. Lifetimes
    3. 4.3. Limits of Lifetimes
    4. 4.4. Lifetime Elision
    5. 4.5. Unbounded Lifetimes
    6. 4.6. Higher-Rank Trait Bounds
    7. 4.7. Subtyping and Variance
    8. 4.8. Drop Check
    9. 4.9. PhantomData
    10. 4.10. Splitting Borrows
  5. 5. Type Conversions
    1. 5.1. Coercions
    2. 5.2. The Dot Operator
    3. 5.3. Casts
    4. 5.4. Transmutes
  6. 6. Uninitialized Memory
    1. 6.1. Checked
    2. 6.2. Drop Flags
    3. 6.3. Unchecked
  7. 7. Ownership Based Resource Management
    1. 7.1. Constructors
    2. 7.2. Destructors
    3. 7.3. Leaking
  8. 8. Unwinding
    1. 8.1. Exception Safety
    2. 8.2. Poisoning
  9. 9. Concurrency
    1. 9.1. Races
    2. 9.2. Send and Sync
    3. 9.3. Atomics
  10. 10. Implementing Vec
    1. 10.1. Layout
    2. 10.2. Allocating
    3. 10.3. Push and Pop
    4. 10.4. Deallocating
    5. 10.5. Deref
    6. 10.6. Insert and Remove
    7. 10.7. IntoIter
    8. 10.8. RawVec
    9. 10.9. Drain
    10. 10.10. Handling Zero-Sized Types
    11. 10.11. Final Code
  11. 11. Implementing Arc and Mutex

Unbounded Lifetimes

Unsafe code can often end up producing references or lifetimes out of thin air. Such lifetimes come into the world as unbounded. The most common source of this is dereferencing a raw pointer, which produces a reference with an unbounded lifetime. Such a lifetime becomes as big as context demands. This is in fact more powerful than simply becoming 'static, because for instance &'static &'a T will fail to typecheck, but the unbound lifetime will perfectly mold into &'a &'a T as needed. However for most intents and purposes, such an unbounded lifetime can be regarded as 'static.

Almost no reference is 'static, so this is probably wrong. transmute and transmute_copy are the two other primary offenders. One should endeavor to bound an unbounded lifetime as quickly as possible, especially across function boundaries.

Given a function, any output lifetimes that don't derive from inputs are unbounded. For instance:

fn get_str<'a>() -> &'a str;Run

will produce an &str with an unbounded lifetime. The easiest way to avoid unbounded lifetimes is to use lifetime elision at the function boundary. If an output lifetime is elided, then it must be bounded by an input lifetime. Of course it might be bounded by the wrong lifetime, but this will usually just cause a compiler error, rather than allow memory safety to be trivially violated.

Within a function, bounding lifetimes is more error-prone. The safest and easiest way to bound a lifetime is to return it from a function with a bound lifetime. However if this is unacceptable, the reference can be placed in a location with a specific lifetime. Unfortunately it's impossible to name all lifetimes involved in a function.