Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

The second principle of memory in Rust is borrowing. Instead of giving the ownership of a value to another part of the code, we give a reference to it. We may give:

19.2.1Defining a reference

Here is the definition of a reference on an integer variable:

16
()

19.2.2Dereferencing

Most of the time a reference cannot be used as is. The following equality test cannot compile because a is a i32, while b is a &i32:

[E0277] Error: can't compare `{integer}` with `&{integer}`
   ╭─[ command_3:1:1 ]
   │
 3 │ 16 == b
   │    ─┬ │ 
   │     ╰─── no implementation for `{integer} == &{integer}`
   │       │ 
   │       ╰─ help: consider dereferencing here: `*`
───╯

The compiler gives us the solution to make it work. We need to use the dereferencing operator * that will convert back the &i32 into a i32:

true
()
    ┌────────────────┐         ┌────────┐
    │ b (0xa413b...) │────────>│ a (16) │
    └────────────────┘         └────────┘

The type of b is thus a reference on an integer, but it is also a regular variable. As a consequence, we can also make a reference on b. Let us define c a variable that is a reference on b:

    ┌────────────────┐         ┌────────────────┐         ┌────────┐
    │ c (0x9c1f7...) │────────>│ b (0xa413b...) │────────>│ a (16) │
    └────────────────┘         └────────────────┘         └────────┘

To test c against b we need to dereference it. To test c against a’s value we need to dereference it twice:

true
true
()

19.2.3Passing a reference

When passing a value by reference to a function, we need to declare the reference both in the function definition and the function call:

16

If we want to access the referenced value directly, we need to use the dereferencing operator *:

18

19.2.4The ref pattern

The ref keyword can be used in place of the & operator.

For instance when defining a new variable:

(10, 10, true)
()

If we define a function that takes a reference, we see that we can pass b directly to the function, since it is already a reference:

12
()

The ref keyword is useful when writing match expressions, like in if let. Let us define an Option value, and write a match using the ref keyword to make the variable n a reference on the internal value of a instead of a copy of the value:

15
()

If we have a mutable Option value, we can get a mutable reference on the internal value using ref and mut together. This allows us to modify the internal value, which we can check afterward:

Some(25)
()

19.2.5Indexing a vector

When indexing a vector of a non-copiable type (i.e.: a type that does not implement the Copy trait) using the [] operator, the values have to be moved out of the collection (i.e.: the ownership passes from the collection to the caller). Hopefully, the compiler forbids this usage of the [] operator.

see solution

19.2.6Mutable reference

If a variable is mutable, we may define a mutable reference on it in order to be able to modify the value:

20
()

When passing a mutable reference to a function, both references in the function call and in the function definition must be declared mutable:

"abcdef"

19.2.7Borrowed mutable variable

While borrowed, a mutable variable is not freely accessible. Only after the reference’s scope termination will we get back full access to the original variable.

When a mutable variable is immutably borrowed, we may access its value and use it:

(b, c)=(16, 21)
8

But we cannot modify it:

[E0506] Error: cannot assign to `a` because it is borrowed
   ╭─[ command_15:1:1 ]
   │
 2 │ let b = &a;
   │         ─┬  
   │          ╰── `a` is borrowed here
 3 │ a = 8;
   │ ──┬──  
   │   ╰──── `a` is assigned to here but it was already borrowed
   │ 
   │ Note: note: requirement that the value outlives `'static` introduced here
───╯

When a mutable variable is mutably borrowed, we may neither access nor modify its value:

[E0503] Error: cannot use `a` because it was mutably borrowed
   ╭─[ command_16:1:1 ]
   │
 2 │ let b = &mut a;
   │         ───┬──  
   │            ╰──── `a` is borrowed here
 3 │ let c = a + 5;
   │         ┬  
   │         ╰── use of borrowed `a`
 4 │ (b, c)
   │  ┬  
   │  ╰── borrow later used here
───╯

19.2.8Multiple references

As said earlier, multiple immutable references on the same variable are allowed:

(8, 8, 8)
()

However it is forbidden to define multiple mutable references on the same variable:

[E0499] Error: cannot borrow `s` as mutable more than once at a time
   ╭─[ command_18:1:1 ]
   │
 2 │ let t = &mut s;
   │         ───┬──  
   │            ╰──── first mutable borrow occurs here
 3 │ let u = &mut s;
   │         ───┬──  
   │            ╰──── second mutable borrow occurs here
 4 │ (t, u)
   │  ┬  
   │  ╰── first borrow later used here
───╯

Or to define a mutable reference while at least one immutable reference exists:

[E0502] Error: cannot borrow `s` as mutable because it is also borrowed as immutable
   ╭─[ command_19:1:1 ]
   │
 4 │   let u = &mut s; // t is still valid since it is used on the line after
   │           ───┬──  
   │              ╰──── mutable borrow occurs here
   │
   ├─[ command_19:1:1 ]
   │
 3 │   let t = &s;
   │           ─┬  
   │            ╰── immutable borrow occurs here
   │ 
 5 │   println!("{:?}", (t, u));
   │                     ┬  
   │                     ╰── immutable borrow later used here
───╯

To solve the issue we need to terminate the scope of t earlier in the code (i.e.: before u is created):

8
8
()

19.2.9Borrowing blocks moving

In the same way borrowing blocks modifications on a mutable variable, it blocks also the moving of ownership.

In the following example, s cannot be moved, because the reference t is still alive:

[E0505] Error: cannot move out of `s` because it is borrowed
   ╭─[ command_21:1:1 ]
   │
 4 │   println!("{:?}", (s, t));
   │                     ┬  
   │                     ╰── move out of `s` occurs here
   │
   ├─[ command_21:1:1 ]
   │
 3 │   let t = &s;
   │           ─┬  
   │            ╰── borrow of `s` occurs here
   │
   ├─[ command_21:1:1 ]
   │
 2 │   let s = String::from("abc");
   │       ┬  
   │       ╰── binding `s` declared here
   │ 
 4 │   println!("{:?}", (s, t));
   │                        ┬  
   │                        ╰── borrow later used here
   │
   ├─[ command_21:1:1 ]
   │
 3 │   let t = &s;
   │             │ 
   │             ╰─ help: consider cloning the value if the performance cost is acceptable: `.clone()`
───╯