References Rules / Borrowing Rules

1. At any given time, we can have either one mutable reference or any number of immutable references.

2. References must always be valid

## Rule 1

At any given time, we can have either one mutable reference or any number of immutable references.

Breaks this rule will cause errors:

• E0499: A variable was borrowed as mutable more than once.

• E0596: This error occurs because you tried to mutably borrow a non-mutable variable.

• E0502: A variable already borrowed as immutable was borrowed as mutable.

### E0499

Erroneous code example:

 1 2 3 4 5  let mut i = 0; let mut x = &mut i; let mut a = &mut i; x; // error: cannot borrow i as mutable more than once at a time 

Output

  1 2 3 4 5 6 7 8 9 10 11  error[E0499]: cannot borrow i as mutable more than once at a time --> src/main.rs:4:17 | 3 | let mut x = &mut i; | ------ first mutable borrow occurs here 4 | let mut a = &mut i; | ^^^^^^ second mutable borrow occurs here 5 | x; | - first borrow later used here For more information about this error, try rustc --explain E0499.

### E0596

This error occurs because you tried to mutably borrow a non-mutable variable.

Erroneous code example:

 1 2  let x = 1; let y = &mut x; // error: cannot borrow mutably 

To fix

 1 2  let mut x = 1; let y = &mut x; 

### E0502

A variable already borrowed as immutable was borrowed as mutable.

Errorneous code example

 1 2 3 4 5 6 7  let mut s = String::from("hello"); let r1 = &s; // no problem let r2 = &s; // no problem let r3 = &mut s; // BIG PROBLEM println!("{}, {}, and {}", r1, r2, r3); 

Error output

  1 2 3 4 5 6 7 8 9 10 11 12 13 14  error[E0502]: cannot borrow s as mutable because it is also borrowed as immutable --> src/main.rs:6:14 | 4 | let r1 = &s; // no problem | -- immutable borrow occurs here 5 | let r2 = &s; // no problem 6 | let r3 = &mut s; // BIG PROBLEM | ^^^^^^ mutable borrow occurs here 7 | 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used here For more information about this error, try rustc --explain E0502. error: could not compile ownership due to previous error

## Rule 2

References must always be valid.

Dangling References: In languages with pointers, it’s easy to erroneously create a dangling pointer, a pointer that references a location in memory that may have been given to someone else, by freeing some memory while preserving a pointer to that memory. In Rust, by contrast, the compiler guarantees that references will never be dangling references: if you have a reference to some data, the compiler will ensure that the data will not go out of scope before the reference to the data does.

Breaks the rule 2 will cause errors

• E0106: This error indicates that a lifetime is missing from a type.

• E0507: A borrowed value was moved out.

### E0106

This error indicates that a lifetime is missing from a type. If it is an error inside a function signature, the problem may be with failing to adhere to the lifetime elision rules.

Errorneous code examples

 1 2 3 4 5 6 7 8  fn main() { let reference_to_nothing = dangle(); } fn dangle() -> &String { let s = String::from("hello"); &s } 

### E0507

• A borrowed value was moved out.

• Moving a member out of a mutably borrowed struct

Erroneous code examples:

  1 2 3 4 5 6 7 8 9 10 11 12  use std::cell::RefCell; struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(self) {} } fn main() { let x = RefCell::new(TheDarkKnight); x.borrow().nothing_is_true(); // error: cannot move out of borrowed content } 
 1 2 3 4 5 6 7  error[E0507]: cannot move out of dereference of Ref<'_, TheDarkKnight> --> src/main.rs:11:5 | 11 | x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type TheDarkKnight, which does not implement the Copy trait For more information about this error, try rustc --explain E0507.
  1 2 3 4 5 6 7 8 9 10 11 12  struct Node { point: Box, } fn main() { let n0 = Node { point: Box::new(32), }; let r0 = &n0; let b0 = r0.point; // cannot move out of r0.point which is behind a shared reference println!("{}", b0); } 
  1 2 3 4 5 6 7 8 9 10  error[E0507]: cannot move out of r0.point which is behind a shared reference --> src/main.rs:10:14 | 10 | let b0 = r0.point; | ^^^^^^^^ | | | move occurs because r0.point has type Box, which does not implement the Copy trait | help: consider borrowing here: &r0.point For more information about this error, try rustc --explain E0507.

It is fine only if you put something back. mem::replace can be used for that:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  use std::mem; #[derive(Debug)] struct Node { point: Box, } fn main() { let mut n0 = Node { point: Box::new(32), }; let r0 = &mut n0; let b0 = mem::replace(&mut r0.point, Box::new(0)); println!("{}", b0); println!("{:?}", r0); println!("{:?}", n0); }