Borrowing

In Rust, it can be useful to use a value's content without taking ownership of the value. To do this, you can take a reference to a value, borrowing it, instead of taking ownership of the value. Here is an example of a signature of a function which gets the length of a StringThis links to official Rust documentation.

ExampleEdit

fn string_len(string: &String) -> usize {
    ...
}

Here, the string is never owned by the function, but instead the function owns a reference to the string (&String).

ReferencesEdit

In the above example we saw use of the & type, which is called a shared reference. The & type prevents mutating the data it points to, and so it is safe for it to be shared among multiple borrows. There is also the &mut type, called a mutable or exclusive reference, which allows mutating the data it points to. &mut is not safe to be shared between multiple borrows, because Rust guarantees the absence of data races. If a value could be accessed while it's being modified in a different thread without synchronization, this could lead to undefined behavior, which is bad, so Rust forbids this.

Every value can either be fully owned, borrowed by multiple shared references or borrowed by exactly one mutable (exclusive) reference.

// Create a value x, which is fully owned.
let mut x: i32 = 5;

{
    // Take a shared borrow of x.
    let y: &i32 = &x;
    // Take another shared borrow of x. This is OK because neither y nor z
    // can mutate x, so it won't change when either of them are reading it.
    let z: &i32 = &x;
    // ERROR: Because x is borrowed you can't perform operations on it.
    // Note: This does technically compile because y and z aren't used
    // after this point, but if y or z were used it wouldn't.
    x += 2;
}
// Since y and z are now out of scope, x has gone back to being fully owned.
{
    // Take a mutable borrow of x.
    let y: &mut i32 = &mut x;

    // The following is NOT accepted by the compiler:
    // let z: &mut i32 = &mut x;
    //
    // Since a mutable reference to x has already been taken, another one
    // can't exist at the same time.
}

Returning referencesEdit

Because references only point to data instead of owning it, you cannot return a reference to local data owned by the current function, because that data is dropped and no longer accessible once the function has exited. This code doesn't compile:

fn return_reference() -> &String {
    let s = "Hello World".to_owned();
    &s
}

s is destroyed at the end of the function, so a reference to it would be invalid, but Rust is able to prevent this. The solution to this is to return an owned String instead of a reference.

However, you can return references from functions if they are derived from references in the parameters. For example:

fn remove_first_byte(s: &str) -> &str {
    &s[1..]
}

This code is valid because the returned reference borrows a string which is not owned by the current function. Rust enforces this system via the use of lifetimes. The above code is equivalent to:

fn remove_first_byte<'a>(s: &'a str) -> &'a str {
    &s[1..]
}

Now you can see why the initial code didn't work; there was no lifetime to assign to the returned String type.