Borrowing

In real life applications, most of the times we have to pass variable bindings to other functions or assign them to other variable bindings. In this case, we are referencing the original binding; borrow the data of it.

What is Borrowing?

Borrow (verb)
To receive something with the promise of returning it.

Shared & Mutable borrowings

⭐️ There are two types of Borrowing,

  1. Shared Borrowing (&T)

    • A piece of data can be borrowed by a single or multiple users, but data should not be altered.
  2. Mutable Borrowing (&mut T)

    • A piece of data can be borrowed and altered by a single user, but the data should not be accessible for any other users at that time.

Rules for borrowings

There are very important rules regarding borrowing,

  1. One piece of data can be borrowed either as a shared borrow or as a mutable borrow at a given time. But not both at the same time.

  2. Borrowing applies for both copy types and move types.

  3. The concept of Liveness

fn main() {
  let mut a = vec![1, 2, 3];
  let b = &mut a;  //  &mut borrow of `a` starts here
                   //  ⁝
  // some code     //  ⁝
  // some code     //  ⁝
}                  //  &mut borrow of `a` ends here


fn main() {
  let mut a = vec![1, 2, 3];
  let b = &mut a;  //  &mut borrow of `a` starts here
  // some code

  println!("{:?}", a); // trying to access `a` as a shared borrow, so giving an error
}                  //  &mut borrow of `a` ends here


fn main() {
  let mut a = vec![1, 2, 3];
  {
    let b = &mut a;  //  &mut borrow of `a` starts here
    // any other code
  }                  //  &mut borrow of `a` ends here

  println!("{:?}", a); // allow borrowing `a` as a shared borrow
}

💡 Let’s see how to use shared and mutable borrowings in examples.

Examples for Shared Borrowing

fn main() {
    let a = [1, 2, 3];
    let b = &a;
    println!("{:?} {}", a, b[0]); // [1, 2, 3] 1
}


fn main() {
    let a = vec![1, 2, 3];
    let b = get_first_element(&a);

    println!("{:?} {}", a, b); // [1, 2, 3] 1
}

fn get_first_element(a: &Vec<i32>) -> i32 {
    a[0]
}

Examples for Mutable Borrowing

fn main() {
    let mut a = [1, 2, 3];
    let b = &mut a;
    b[0] = 4;
    println!("{:?}", b); // [4, 2, 3]
}


fn main() {
    let mut a = [1, 2, 3];
    {
        let b = &mut a;
        b[0] = 4;
    }

    println!("{:?}", a); // [4, 2, 3]
}


fn main() {
    let mut a = vec![1, 2, 3];
    let b = change_and_get_first_element(&mut a);

    println!("{:?} {}", a, b); // [4, 2, 3] 4
}

fn change_and_get_first_element(a: &mut Vec<i32>) -> i32 {
    a[0] = 4;
    a[0]
}