Created
March 2, 2015 09:41
-
-
Save jviereck/cfec31c10e94e632d0a7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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