2.14 Borrowing

To make sure another binding does not steal our resources and takes ownership of them, we may use something called ‘borrowing’: which is in terms of some other low-level computer languages ‘referencing a certain resource’.

Rather than giving the resource away, we lend out a pointer to that resource (or a handle), which the binding we lent it to can in turn use however it would like, depending on what type of a reference (or type of a handle) we give it.

References

Let us create a function that takes references instead of the actual bindings’ resources, meaning we lend it the values rather than giving it to them:

fn main()
{
	let a = String::new();

	borrow(&a);

	println!("My master remains the same: {}.", a);
}

fn borrow(b: &String)
{
	println!("I am borrowing: {}.", b);
}

This code will correctly print out in the terminal:

I am borrowing: .
My master remains the same: .

That is awesome!

We use & prior to something in order to make it a reference. Inside the function, we use it before the type to tell Rust that the provided argument will be of type &String, which is a reference to a String. Once calling the function, we use & in front of the binding name, in order to take its reference: thus ending up lending out a to the borrow function, which gladly borrows it.

When something borrows a resource from another binding, it is guaranteed to give it back at the end of a scope.

Scopes

Every code-block is its own scope. Borrowed resources sieze being borrowed upon the borrowing binding going out of scope (commenting the previous function):

fn main()
{
	// Create a new String
	let a = String::new();

	// Go to function, called with reference 
	// of ‘a’, lending it
	borrow(&a); 

	// Got its variable back after lending it
	// This will print with no trouble whatsoever
	println!("My master remains the same: {}.", a);
}

// Binding ‘b’ enters into scope, 
// bound to a reference given by ‘a’
fn borrow(b: &String)
{
	// Print out borrowed value
	println!("I am borrowing: {}.", b);
	
	// Upon entering next line, ‘b’ will go out of 
	// scope, ending up giving back its borrowed 
	// reference to ‘a’ since ‘b’ no longer exists
}

It does now actually matter whether or not we get back a regular & reference after lending it to another binding. You may have an unlimited amount of these referencing the same piece of memory. Because of this, the following works just fine:

fn main()
{
	let a = String::new();
	let b = &a;

	println!("{}", a);
}

Thus thus works for the fact that & references are not mutable, but there are references which are.

Mutability

Whilst a regular & reference is not mutable, there is another one that is &mut:

fn main()
{
	let mut a = String::new();
	let b = &mut a;

	println!("{}", a);
}

This will not work, for the same reason that you cannot use a reference once another binding has taken ownership of it. The &mut reference, you may use in order to change the value of the resource. Doing so would mean possible security breaches within Rust, and Rust is built for safety.

Let us introduce a new scope within our current one, in order to change the value of a to something of String::from, which creates a String from a piece of text:

fn main()
{
	// Define blank String bound to ‘a’
	let mut a = String::new();
	
	// Introduce new scope here
	{
		// Create new binding inside scope, bound to 
		// a mutable reference to the resource of ‘a’
		let b = &mut a;

		// Use * in order to dereference it, thus 
		// yielding actual changable data, rather 
		// than a simple reference
		*b = String::from("Changed it!");
		
	// Scope ends, ‘b’ gets removed. Borrowed resources
	// are given back to its rightful owners
	}
	
	// The resource bound to ‘a’ has been given back, 
	// ‘a’ may print out as it normally would
	println!("{}", a);
}

As the comment highly suggests, * dereferences a reference, from pointer to fully changable value (in the case of &mut).

New scopes may be introduced wherever you feel like one should go. This scope obviously does not help much as we could have acchieved the same outcome by just changing a directly. However, since this is what we are using, do make sure that the binding borrowing an &mut is mutable, otherwise it cannot lend out a mutable reference.

Functions

The &mut can quite obviously be borrowed to functions as well. Make sure that you specify in the function parameters that the specific parameter is of type &mut of something, as well as the argument being entered into the function takes the &mut reference of itself:

fn mutable_fn(b: &mut String)
{
	// ...
}

As well as upon calling it:

let mut a = String::from("Hello, world!");

mutable_fn(&mut a);

Do this, and it will work wonderfully well!

Moreover

Since mutable references may be used to edit the contents of the original binding’s resource, you may only have one of those at one time.

  • You may only have one mutable reference at one time: this means that the owning binding cannot be used, for as long as the borrowing binding taking the mutable reference is in scope.
  • You may have an unlimited amount of regular references, as you cannot change the binding’ resource’s value using them.

It is all highly logical!

Exercises

  • Create a function which changes the value of the variable it takes as an argument. Print out the variable specified right after calling the function to change its value.

Conclusion

Borrowing is the way to go when you do not wish to give a value away from one binding to another, and the type of a certain binding clearly does not implement the Copy trait.