2.13 Ownership

Ownership is one of Rust’s features which makes it somewhat special. Every name of a variable binding bound to a value has the ownership of that particular value:

let a = String::new();

// Next piece of code goes here

The variable binding a has the ownership of the String it has been bound to. Let us expand upon this, by entering more code at the comment ‘Next piece of code goes here’:

let b = a;

println!("{}", a);

This will print an error:

error[E0382]: use of moved value: `a`
 --> src\main.rs:6:20
  |
4 |     let b = a;
  |         - value moved here
5 |
6 |     println!("{}", a);
|                    ^ value used here after move

We are creating another variable binding by the name of b, which ‘takes ownership’ of the value from variable binding a. Only one variable binding may have ownership of a resource at a time. Thus, this generates for us a rather nice error.

This means that as for binding a, its value has been moved to another location. It no longer has the right to access the resource it was previously bound to.

But why?

The reason for this is simple, consider this horrible procedure:

  • There is a variable binding a bound to a vector containing two elements.
  • Another variable binding b takes on the same resource, from the same location in memory, as the first one.
  • The first variable binding a adds an element to the vector.
  • The second variable binding b thinks it contains two elements, whilst a knows it contains three.

This is for the fact that the length of the array is stored together with its name on the stack, whilst the actual values are stored on the heap. All of a sudden we have a huge problem, as the two bindings linked with the same resource thinks it is of different lengths.

Just imagine what disastrous things would happen if the actual resource was one elements in size, whilst a variable binding thinks it is two elements or more in size. There would be no such thing to retrieve the value from.

Copy

There are something called traits in rust, which will be discussed at a later time. Traits add a sort of behavior to different types, which in this case, implementing the Copy trait, makes them copy data to another variable binding, rather than giving them ownership of it:

let a = 3;
let b = a;

println!("{}", a);

This works very well. As b copies all the contents from a’s resources, it never takes ownership of them. The two variable bindings in this example will be interpreted by the compiler as i32. That type for one, contains the Copy trait.

Functions

Contemplate upon the following, as well as the meaning of life should you feel like it:

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

	steal(a);

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

fn steal(b: String)
{
	println!("I stole a piece of text!");
}

This will generate a similar error to that of the first example in this section. By giving a to steal, a loses ownership over the variable to the parameter b of steal.

Give it back!

Surely a would get mad and ask to have its resource back. Let us modify all this a slight bit:

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

	a = steal(a);

	println!("But I got it back: {}.", a);
}

fn steal(b: String) -> String
{
	println!("I stole a piece of text!");
	
	b // Return b to the place it was called
}

This will print:

I stole a piece of text!
But I got it back: .

Hurrah, we got our resource back! Whilst this technically will work, there would be somewhat of a problem if our function took a great deal of arguments, as we would need to return every single one of them.

Luckily, there is a solution for this, which will be discussed in the next section.

The reason the printed version of the String does not display, is that it is an empty such. We created a blank string upon calling String::new: that it was is being shown.

Exercises

  • Create a function which takes three arguments and return them back inside a tuple. Retrieve the arguments using let dereferencing let (a, b, c) = func();.
  • Get really mad at the first exercise because it will feel completely pointless once you have read through the following section.

Conclusion

Variable bindings are evil. They take things without asking kindly. Therefore, we are going to need to do something about them and that is exactly what we will do during the next section of this chapter.