Skip to content

Instantly share code, notes, and snippets.

@jviereck
Created March 2, 2015 09:41
Show Gist options
  • Save jviereck/cfec31c10e94e632d0a7 to your computer and use it in GitHub Desktop.
Save jviereck/cfec31c10e94e632d0a7 to your computer and use it in GitHub Desktop.
// Goal of this file:
// Figure out how the lifetimes of a mutable reference is exactly defined
// and what happens if a `&mut` reference A is assigned to another `&mut`
// reference B - is the lifetime of B inheriated from A or does the lifetime
// of B depends on the location of the definition of B?
struct Entry<'a> {
id: isize,
next: Option<&'a mut Entry<'a>>,
}
fn main() {
let mut entryA = Entry { id: 0, next: None };
let mut entryB = Entry { id: 1, next: None };
let mut entryC = Entry { id: 2, next: None };
// Create a mutable borrow from the `entryA` value. The borrow only lasts
// for the length of the block the `let entry_ref0` is defined in.
{
let entry_ref0 : &mut Entry = &mut entryA;
entry_ref0.id = 0;
// This `println!` is not permitted by the compiler as the `entry_ref`
// is stil mutable borrowed:
// error: cannot borrow `entryA.id` as immutable because `entryA` is
// also borrowed as mutable
// println!("entryA.id = {}", entryA.id);
}
// This immutable borrow of `entryA` works fine and shows, that the borrow
// from `entry_ref0` has ended.
println!("entryA.id = {}", entryA.id);
// In the following a mutable borrow is taken from `entryA` and assigned
// to a field of `entryB`. This causes the borrow on the `entryA` to outlast
// the block the `entry_ref` is defined in. In particular, in contrast to the
// pervious example, the mutable borrow is NOT returned at the end of the
// block scope!
{
let entry_ref : &mut Entry = &mut entryA;
entryB.next = Some(entry_ref);
// Does the compiler perform a detailed analysis on the borrowing? E.g.
// if the `entryB.next` is reset, does the compiler removes the
// mutable borrow on `entry_ref` after the block?
// ANSWER: Nope, the compiler is not that smart and performs and
// overestimation on the borrowing of the `entryA` value.
entryB.next = None;
}
// As the compiler assumes a reference of `entryA` to be stored on the
// `entryB.next` field, the `entryA` is still assumed to be mutable borrowed
// and therefore the following immutable borrow for the `println!` is
// rejected by the comppiler:
// error: cannot borrow `entryA.id` as immutable because `entryA` is also
// borrowed as mutable
println!("entryA.id = {}", entryA.id);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment