🎓 A1Learner
🔍
0 of 142 lessons completed

Rust Borrowed Arguments

A borrowed argument is a function parameter that takes a borrowed view, such as &str or &[T]. The view accepts more kinds of caller than an owned-form parameter.

A parameter that asks for too much

It works, but only for a String. A text literal is a &str, and a &str is never turned into a &String for you.

fn shout(word: &String) -> String {
    word.to_uppercase()
}

Ask for the borrowed view instead

Change one word. The body stays exactly the same.

fn shout(word: &str) -> String {
    word.to_uppercase()
}

Now every caller fits

A String, a literal, and a slice of a String all pass — the compiler fits each one to &str.

let owned = String::from("rust");
println!("{}", shout(&owned));
println!("{}", shout("rust"));
println!("{}", shout(&owned[0..2]));

The same trick for lists

A function that totals numbers does not need a Vec. It needs a view of some numbers.

fn total(numbers: &[i32]) -> i32 {
    numbers.iter().sum()
}

One function, many shapes

A whole array, a fresh array, and the tail of the first one — all of them are an &[i32].

let a = [1, 2, 3];
println!("{}", total(&a));
println!("{}", total(&[10, 20]));
println!("{}", total(&a[1..]));

Example

fn shout(word: &str) -> String {
    word.to_uppercase()
}

fn total(numbers: &[i32]) -> i32 {
    numbers.iter().sum()
}

fn main() {
    let owned = String::from("ferris");
    println!("{}", shout(&owned));
    println!("{}", shout("crab"));
    let scores = [4, 5, 6];
    println!("total = {}", total(&scores));
    println!("last two = {}", total(&scores[1..]));
}

Key points

  • Borrowed view: every owned type has one — &str views a String, &[T] views a Vec<T>, &Path views a PathBuf
  • Use the borrowed view as the parameter type whenever a function only reads.
  • It accepts the owned value.
  • It accepts literals.
  • It accepts slices of the value.
  • Deref coercion does the fitting for you.
  • A &String is accepted where &str is expected.
  • A &Vec<T> is accepted where &[T] is expected.
  • The fitting runs one way only.
  • A &str is never grown into a &String for you.
  • Growing one would need a fresh allocation.

In this example, shout takes a &str and total takes an &[i32]. main hands shout two different things. &owned borrows the String. "crab" is already a &str. Both fit the same parameter. total is called first with the whole array, then with &scores[1..], a slice of its last two items. No value is copied or moved into either function: the borrowed views simply look at what is already there.

Note

The standard library follows this idiom everywhere.

Text methods ask for &str.

List methods ask for &[T].

Borrowed views are the normal way in.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

A function only reads a list of names to count them. Which parameter type accepts the most callers?