Activity 17 - Be the Borrow Checker!

For each code snippet below:

  1. Circle each borrow
  2. Draw a box or bracket around each borrow's scope (from creation to last use)
  3. Label each borrow scope as & (immutable) or &mut (mutable)
  4. Mark any conflicts where borrows violate the rules
  5. Decide whether the code will compile or not (and if not, why not)

Borrow Checker Rules:

  • Rule 1: You can have EITHER many immutable references OR one mutable reference (not both)
  • Rule 2: References must be valid (can't outlive the data they point to)

Problem 1 - let's do it together

fn main() {
    let mut scores = vec![85, 92, 78];

    let reader = &scores;
    println!("Current scores: {:?}", reader);

    let writer = &mut scores;
    writer.push(95);

    println!("Updated scores: {:?}", writer);
}

Problem 2

fn main() {
    let data = vec![1, 2, 3];

    let ref1 = &data;
    let ref2 = &data;
    let ref3 = &data;

    println!("{:?}", ref1);
    println!("{:?}", ref2);
    println!("{:?}", ref3);
    println!("{:?}", data);
}

Problem 3

fn main() {
    let mut numbers = vec![1, 2, 3, 4, 5];

    for num in numbers.iter() {
        println!("{}", num);
        let num_ref = &mut numbers;
        num_ref.push(*num * 2);
    }
}

Fun (and useful) fact - the same thing happens when you do numbers.push() without let ...


Problem 4

fn main() {
    let mut text = String::from("Hello");

    let read = &text;
    println!("{}", read);

    let write = &mut text;
    write.push_str(" World");
    println!("{} {}", read, write);
}

Problem 5

fn main() {
    let mut data = vec![10, 20, 30];

    let sum = calculate_sum(&data);
    add_bonus(&mut data, 5);

    println!("Sum: {}, Data: {:?}", sum, data);
}

fn calculate_sum(numbers: &Vec<i32>) -> i32 {
    numbers.iter().sum()
}

fn add_bonus(numbers: &mut Vec<i32>, bonus: i32) {
    for num in numbers.iter_mut() {
        *num += bonus;
    }
}

Problem 6

fn main() {
    let outer; // this creates the variable at this scope and lets you set it to a value later
    {
        let inner = vec![1, 2, 3];
        outer = &inner;
        println!("Inside: {:?}", outer);
    }
    println!("Outside: {:?}", outer);
}

Problem 7

fn main() {
    let mut values = vec![1, 2, 3];

    let modifier1 = &mut values;
    modifier1.push(4);
    println!("After first: {:?}", modifier1);

    let modifier2 = &mut values;
    modifier2.push(5);
    println!("After second: {:?}", modifier2);
}

Problem 8

fn create_message() -> &String {
    let msg = String::from("Hello");
    return &msg;
}

fn main() {
    let message = create_message();
    println!("{}", message);
}

Problem 9

fn main() {
    let mut data = vec![1, 2, 3];

    let first = &data[0];
    data.push(4);

    println!("First element: {}", first);
}