Borrowing a value

On the other hand we can borrow the resource by making a (mutable) reference kl2 to klaatu with:

let kl2 = &klaatu;         // a borrow or reference 

Or:

let kl2 = &mut klaatu; // a mutable borrow or reference 

A borrow is a temporary reference, passing the address of the data structure through &. The borrowed reference can access the contents of the memory location, but does not own the value. The owner gives up full control over a borrowed value while it is being borrowed.

Now, in the case of the mutable borrow, kl2 can change the object, for instance when our alien loses a tentacle in a battle:

   kl2.n_tentacles = 14; 
   println!("{} - {}", kl2.planet, kl2.n_tentacles);  

This prints out the following output:

    Venus - 14  

But if we try to change the alien's planet through klaatu, we can do it as follows:

klaatu.planet = "Pluto".to_string(); 

We get the following error:

    error: cannot assign to `klaatu.planet` because it is borrowed  

It was indeed borrowed by the kl2 reference.

Like in everyday life, while an object is borrowed, the owner does not have access to it as it is no longer in its possession. In order to change the resource, klaatu needs to own it, without the resource being borrowed at the same time.

Rust even explains this to us with the note it adds:

    borrow of `klaatu.planet` occurs here ownership.rs:18    let kl2 = &mut klaatu;  

Because kl2 borrows the resource, Rust also even forbids us to access the instance with its former name klaatu:

println!("{} - {}", klaatu.planet, klaatu.n_tentacles); 

The compiler then throws the following error:

    error: cannot borrow `klaatu.planet` as immutable because `klaatu` is also borrowed as mutable.  

When a resource is moved or borrowed, the (original) owner can no longer use it. This prevents the memory problem that is known as a dangling pointer, which is the use of a pointer that points to an invalid memory location.

But here is a revelation: if we isolate the borrowing by kl2 in its own block, like in:

// see code in Chapter 7/code/ownership2.rs 
fn main() { 
    let mut klaatu = Alien{ planet: "Venus".to_string(),    n_tentacles: 15 }; 
    {   
      let kl2 = &mut klaatu; 
      kl2.n_tentacles = 14; 
      println!("{} - {}", kl2.planet, kl2.n_tentacles);  
// prints: Venus - 14 
    } 
}

The former problems have disappeared! After the block kl2 can no longer be used, but we can now do for example:

println!("{} - {}", klaatu.planet, klaatu.n_tentacles);
klaatu.planet = "Pluto".to_string(); println!("{} - {}", klaatu.planet, klaatu.n_tentacles);

This prints the following output:

    Venus - 10
    Pluto - 10  

Why is this? Because after the closing } of the code block in which the kl2 reference was bound, its lifetime ended. The borrowing was over (a borrow has to end sometime) and klaatu reclaimed full ownership, and thus the right to change. When the compiler detects that the lifetime of the original owner klaatu eventually ends, the memory occupied by the struct instance is automatically freed.

In fact this is a general rule in Rust: whenever an object goes out of scope and it doesn't have an owner anymore, its destructor is automatically called and the resources owned by it are freed, so that there never can be any memory (or other resource) leaks. This is described in technical terms as Rust obeys the Resource Acquisition Is Initialization (RAII) rule; for more info see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization.

As we experimented in the previous section on References, a resource can be immutably borrowed many times, but while immutably borrowed, the original data can't be mutably borrowed.