Rust's Borrowing and Reference Laws
Tags: rust, tutorial, learning, programming
Published: 2020-08-01 12:02:50

*This post published on my blog [before](https://aligoren.com/rusts-borrowing-and-reference-laws/)*

-----

Hi everyone. Before that, I wrote a post called [Ownership Concept in Rust](https://dev.to/aligoren/ownership-concept-in-rust-61a).

Today I'll try to explain some of the features called borrowing and references. I called them laws in the title.

Before starting, I’ll create a project with cargo;

```bash
cargo new references_and_borrowing

cd references_and_borrowing
```

## Introduction

We've discussed the ownership concept in the last post. When you assign a heap-allocated variable to another one, we also transfer its ownership, and the first variable we created is no longer used. This explains why Rust is a secure programming language. Rust's memory management mechanism is different than others.

For example, when you passed a variable to a function as a parameter, that variable is no longer used. It looks like annoying. You don't want to always create new variables to do the same stuff.

Sometimes you don't want to move variable's ownership but you also want to its data. In these kinds of cases, you can use the borrowing mechanism. Instead of passing a variable as a value, you send a variable as a reference.

References hold memory addresses of variables. They don't hold the data of variables.

## What are Benefits?

![Benefits](https://dev-to-uploads.s3.amazonaws.com/i/y4vznxkk5wzvs15b3ot7.jpg)

*[Image from Freepik](https://www.freepik.com/premium-vector/hand-holding-megaphone-benefits-vector-illustration_6501287.htm)*

The compiler always checks the reference object statically. It doing this with a mechanism called borrow checker. So, it prevents to delete object while it has a reference.

## Let's See Examples

The first example will be like that;

```rust
fn main() {
  let my_name = String::from("Ali");

  //this ampersand is a reference
  let len_name = name_length(&my_name);
  //  -----------------------^
}

fn name_length(string: &String) -> usize {
    // ----------------^
    string.len()
}
```

In the above example, we've passed a variable as a reference. When you use `&` ampersand symbol, it's transforming to a reference. The key point is here if we pass a reference variable to a function as a parameter, that function will accept a reference parameter. If you don't use an ampersand you'll see a compile-time error like that;

```output
 --> src/main.rs:5:32
  |
5 |     let len_name = name_length(&my_name);
  |                                ^^^^^^^^
  |                                |
  |                                expected struct `std::string::String`, found `&std::string::String`
  |                                help: consider removing the borrow: `my_name`
```

Our second example will be like that;

```rust
fn main() {
  let boxed_integer = Box::new(5);
  let reference_integer = &boxed_integer;

  println!("Boxed: {} and Reference {}", boxed_integer, reference_integer);
}
```

As you see, when we send or assign a parameter, our assigned or passed values starts with an ampersand. What would happens if we didn't use this ampersand? It won't work. Because when we assigned `boxed_integer` to `reference_integer`, compiler removed the `boxed_integer` variable.

## A Problem About Removed Resource

![Problem](https://dev-to-uploads.s3.amazonaws.com/i/7evskvd7jkdhjst93owa.jpg)

*[Image from Freepik](https://www.freepik.com/free-vector/group-people-holding-question-mark-icons_3530048.htm)*

Let's think of a scenario. We know that when references are available, the resource won't be removed. What will happen if the resource removed before the reference? Let me say the reference will point to a null unit or random unit. This is a really big problem here. But don't worry about it. The Rust avoids this problem thanks to the compiler. Let's see an example.

```rust
fn a_function(box_variable: Box<u32>) {
    println!("Box Variable {}", box_variable);
}

fn main() {
    let box_variable = Box::new(6);
    let reference_box_var = box_variable;
    
    a_function(box_variable);
    
}
```

We'll see an error here;

```output
error[E0382]: use of moved value: `box_variable`
 --> src/main.rs:9:16
  |
6 |     let box_variable = Box::new(6);
  |         ------------ move occurs because `box_variable` has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
7 |     let reference_box_var = box_variable;
  |                             ------------ value moved here
8 |     
9 |     a_function(box_variable);
  |                ^^^^^^^^^^^^ value used here after move

error: aborting due to previous error; 1 warning emitted
```

To solve this problem, we could create a new scope;

```rust
fn a_function(box_variable: Box<u32>) {
    println!("Box Variable {}", box_variable);
}

fn main() {
    let box_variable = Box::new(6);
    
    // a scope
    {
        let reference_box_var = &box_variable;
    }
    
    a_function(box_variable);
    
}
```

## Mutable Borrow

Until now, we always see immutable borrow examples. But sometimes you will need mutable borrows. We only read values from immutable borrow resources. We didn't change reference's value.

Normally when we accept reference we use this notation `&T` but if we want to mutable reference we should use `&mut T`. However, we can't create a mutable reference while the variable is immutable. Let's see an example

```rust
fn main() {
    let mut a_number = 3;
    
    {
        let a_scoped_variable = &mut a_number;
        *a_scoped_variable +=1;
    }
    
    println!("A number is {}", a_number); // A number is 4
    
}
```

```rust
let a_scoped_variable = &mut a_number;
*a_scoped_variable +=1;
```

In the above example, if we didn't use `mut` the following line won't work. And if we didn't create a variable with the `mut` keyword at the beginning, the compiler will throw an error. Because we were trying to get a mutable reference from an immutable variable.

There is also a key point we should know that you can have only one mutable reference. So you can't create multiple mutable references. I give an example that will fail.

```rust
fn main() {
    let mut number = Box::new(5);
    
    let number2 = &mut number;
    let number3 = &mut number;
    
    println!("{}, {}", number2, number3);
}
```

It will show an error like that;

```rust
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `number` as mutable more than once at a time
 --> src/main.rs:5:19
  |
4 |     let number2 = &mut number;
  |                   ----------- first mutable borrow occurs here
5 |     let number3 = &mut number;
  |                   ^^^^^^^^^^^ second mutable borrow occurs here
6 |     
7 |     println!("{}, {}", number2, number3);
  |                        ------- first borrow later used here

```

> The benefit of having this restriction is that Rust can prevent data races at compile time. A data race is similar to a race condition and happens when these three behaviors occur:


    1-) Two or more pointers access the same data at the same time.
    2-) At least one of the pointers is being used to write to the data.
    3-) There’s no mechanism being used to synchronize access to the data.

We can fix this error by creating a new scope;

```rust
fn main() {
    let mut number = Box::new(5);
    
    let number2 = &mut number;
    
    {
        let number3 = &mut number;
    }
    
}
```

There is a similar rule like this rule when you're combining mutable and immutable references.

```rust
fn main() {
    let mut number = Box::new(5);
    
    let number2 = &number;
    let number3 = &mut number;
    
    println!("Number2 {} and Number3 {}", number2, number3);
    
}
```

This code piece won't work. You'll get an error;

```output
Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `number` as mutable because it is also borrowed as immutable
 --> src/main.rs:5:19
  |
4 |     let number2 = &number;
  |                   ------- immutable borrow occurs here
5 |     let number3 = &mut number;
  |                   ^^^^^^^^^^^ mutable borrow occurs here
6 |     
7 |     println!("Number2 {} and Number3 {}", number2, number3);
  |                                           ------- immutable borrow later used here
```

We can fix this code by this way;

```rust
fn main() {
    let mut number = Box::new(5);
    
    let number2 = &number;
    
    println!("Number2 {}", number2);
    
    let number3 = &mut number;
    
    println!("Number3 {}", number3);
}
```

It worked. Because a reference’s scope starts from where it is introduced and continues through the last time that reference is used.

## Dangling References

In languages which have pointers, you can create dangling pointers easily. For example, this problem occurs in C programming language like that;

```c
int *afunc();
void main()
{
  int *pointer;
  pointer = afunc();

  fflush(stdin);
  printf("%d", *pointer);
}

int * afunc()
{
  int x = 1000;
  ++x;

  return &x;
}
```

It should throw an output like that;

> warning: function returns the address of the local variable

So, what's happening in Rust programming language? The compiler guarantees that references will never be dangling references. For example, you wrote code like the above code, the compiler, won't compile your code. It will ensure that the data will not go out of scope before the reference to the data does.

Let's try to create a dangling reference and we'll sure Rust will prevent to compile your code.

```rust
fn main() {
    let dangling_reference = a_func();
}

fn a_func() -> &Box<u8> {
    let x = Box::new(10);
    
    &x
}
```

We'll see an error at compile-time;

```output
Compiling playground v0.0.1 (/playground)
error[E0106]: missing lifetime specifier
 --> src/main.rs:5:16
  |
5 | fn a_func() -> &Box<u8> {
  |                ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
  |
5 | fn a_func() -> &'static Box<u8> {
  |                ^^^^^^^^
```

As you see, our code didn't compile. The solution is to return your data directly. Don't use ampersand.

```rust
fn main() {
    let dangling_reference = a_func();
}

fn a_func() -> Box<u8> {
    let x = Box::new(10);
    
    x
}
```

## What Did We Learn?

![What Did We Learn](https://dev-to-uploads.s3.amazonaws.com/i/pr3ba9jxcylrm7pd2m94.jpg)

*[Image from Freepik](https://www.freepik.com/free-vector/online-tutorials-concept_7915189.htm)*

- At any given time, you can have either one mutable reference or any number of immutable references.
- References must always be valid.

That’s all for now. If there is something wrong, please let me know.

Thanks for reading.

## Resources

- [References and Borrowing](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html)
- [Rust'ta Borrowing ve Referans Kavramları (Turkish)](https://canaltinova.com/blog/posts/rustta-borrowing-ve-referans-kavramlari/)