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?