singularity

Borrowing & Lifetimes

Shared References

fn cache(input: &i32, sum: &mut i32) {
  *sum = *input + *input;
  assert_eq!(*sum, 2 * *input);
}

Listing 1-4

Mutable References

fn noalias(input: &i32, output: &mut i32) {
  if *input == 1 {
    *output = 2;
  }

  if *input != 1 {
    *output = 3;
  }
}

Listing 1-5

let x = 42;
let mut y = &x; // y is of type &i32
let z = &mut y; // z is of type &mut &i32

Listing 1-6

fn replace_with_84(s: &mut Box<i32>) {
  // this is not okay, as *s would be empty:
  // let was = *s;

  /*1 - cannot move value out here since 
        caller will try to free at 5 causing double drop
  */
 
  // but this is:
  let was = std::mem::take(s); 
  /*2 - โ‰ˆ to std::mem::replace(&mut value, Default::default()); 
        The default is a separate, owned value, so it is safe 
        for the caller to drop it when the scope ends at 5.
  */
  
  // so is this:
  *s = was; 
  /*3 - if you donโ€™t need the old value behind the reference, 
        you can overwrite it with a value that you already own 3, 
        leaving it to the caller to drop the value later.
  */

  // we can exchange values behind &mut:
  let mut r = Box::new(84);

  std::mem::swap(s, &mut r); 
  /* 4 -  if you have two mutable references, you can swap 
          their values without owning either of them since 
          both references will end up with a legal owned 
          value for their owners to eventually free.
  */
  
  assert_ne!(*r, 84);
}

// 5

let mut s = Box::new(42);
replace_with_84(&mut s);

Listing 1-7

Interior Mutability