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

Limits of Lifetimes

Given the following code:

struct Foo; impl Foo { fn mutate_and_share(&mut self) -> &Self { &*self } fn share(&self) {} } fn main() { let mut foo = Foo; let loan = foo.mutate_and_share(); foo.share(); }
struct Foo;

impl Foo {
    fn mutate_and_share(&mut self) -> &Self { &*self }
    fn share(&self) {}
}

fn main() {
    let mut foo = Foo;
    let loan = foo.mutate_and_share();
    foo.share();
}Run

One might expect it to compile. We call mutate_and_share, which mutably borrows foo temporarily, but then returns only a shared reference. Therefore we would expect foo.share() to succeed as foo shouldn't be mutably borrowed.

However when we try to compile it:

<anon>:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable
<anon>:11     foo.share();
              ^~~
<anon>:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends
<anon>:10     let loan = foo.mutate_and_share();
                         ^~~
<anon>:12:2: 12:2 note: previous borrow ends here
<anon>:8 fn main() {
<anon>:9     let mut foo = Foo;
<anon>:10     let loan = foo.mutate_and_share();
<anon>:11     foo.share();
<anon>:12 }
          ^

What happened? Well, we got the exact same reasoning as we did for Example 2 in the previous section. We desugar the program and we get the following:

struct Foo; impl Foo { fn mutate_and_share<'a>(&'a mut self) -> &'a Self { &'a *self } fn share<'a>(&'a self) {} } fn main() { 'b: { let mut foo: Foo = Foo; 'c: { let loan: &'c Foo = Foo::mutate_and_share::<'c>(&'c mut foo); 'd: { Foo::share::<'d>(&'d foo); } } } }
struct Foo;

impl Foo {
    fn mutate_and_share<'a>(&'a mut self) -> &'a Self { &'a *self }
    fn share<'a>(&'a self) {}
}

fn main() {
    'b: {
        let mut foo: Foo = Foo;
        'c: {
            let loan: &'c Foo = Foo::mutate_and_share::<'c>(&'c mut foo);
            'd: {
                Foo::share::<'d>(&'d foo);
            }
        }
    }
}Run

The lifetime system is forced to extend the &mut foo to have lifetime 'c, due to the lifetime of loan and mutate_and_share's signature. Then when we try to call share, and it sees we're trying to alias that &'c mut foo and blows up in our face!

This program is clearly correct according to the reference semantics we actually care about, but the lifetime system is too coarse-grained to handle that.

TODO: other common problems? SEME regions stuff, mostly?