Published on 25th March, 2023

Moves and Indexed Content

When a move happens, Rust leaves the moved variable uninitialized:


When we pass the value of hero to take_ownership(), hero becomes uninitialized since its value has been moved. Rust won't compile because we are printing the value of hero after it has been given to take_ownership().

String data types, willingly give ownership when they are bound to other variables or passed as arguments to functions that aren't borrowing from them.

Scalar Data Types

Other Data types behave differently. Simple Scalar Data types implement the Copy trait. This means Rust will always copy them to the new binding variable or as arguments to other functions.

Indexed Content

Unlike Strings and Rust Scalar Data Types, some complex data types are never willing to hand ownership out. They only give ownership when we use special methods that the standard library (`std`) provides. An example is a vector of Strings.


When we try compiling we get this error. error[E0507]: cannot move out of index of `Vec`

When we bind a new variable to a String variable without borrowing, a move happens leaving the source uninitialized. The destination becomes the owner of the variable.

Using our lang vector example, if we bind C to k_and_r the lang vector would have its index of 3 uninitialized. For this to work, a vector must carry with it additional information showing which of its values are initialized and which aren't.

This adds more complexity to vectors and Rust, a vector should just be a vector and hence Rust doesn't allow us to do bindings like these.

Borrow?

The easy fix would be to not move the value out of the vector but to simply borrow it. Most cases this will be what you need but in rare cases that you really need to move the value out of a vector, Rust provides us with methods which we will be using below.

.pop()



First we set the lang vector to mutable with mut Then we use the .pop() method, to remove the last element of the vector. This might not be very useful in situations where we want to remove a value that is not the last value of the vector.

Using vector's swap_remove method

A vector's swap_remove, takes an index of the vector and removes the value of its last index and replaces it with the index of the value given to it.


std::mem::replace

We can use std::mem::replace to substitute a value at a particular index and replace it with a different value.


It is important to notice that all of these methods move a value out of the vector but still leave the vector complete. Albeit smaller in some cases.

Option<T>

There might be situations where we want to move a value out of its owner that the compiler can't check, in such a situation we could consider changing the type of the value into a type that can dynamically check whether it has a value or not.


The compiler throws error[E0507]: cannot move out of index of Vec<Language>

In line 6 of the code snippet above, we used Option<String> instead of String yet we failed to move the value out. To move the value out we can use the std::mem::replace method demonstrated above. With type Option<String>, we can move the value out and replace it with None. Since an Option<String> is an enum that has two variants of Some() and None.


std::mem::replace moves the value of languages[0].creator out of its owner and passes ownership to rusty. This practice is very common that there is a method for it.

We can rewrite the above line more legibly as


Compiling and running the above prints