191. Accept &str, Not String — Take the Most General Borrow
A function that takes String forces every caller holding a &str to allocate just to call you. Take &str instead — and &[T] over &Vec<T> — and deref coercion lets everyone in for free.
The over-specific signature
This function only ever reads its argument, yet it demands an owned String:
| |
Now a caller with a string literal — the most common case — has to allocate a whole String just to satisfy the type:
| |
Worse, a caller who only has a borrow (say, a field of someone else’s struct) is stuck: they must .clone() or .to_owned() before they can call you, even though you never keep the value.
Take the borrow
If the body only reads, take &str. Deref coercion means &String and string literals both coerce to &str automatically:
| |
Zero allocations at the call site, and every kind of caller just works.
Same rule for slices
The exact parallel exists for vectors. Taking &Vec<T> locks callers into owning a Vec; taking &[T] accepts a Vec, an array, or any slice:
| |
&Vec<T> couldn’t accept that array or that sub-slice at all. &[T] is strictly more flexible and costs nothing.
The general principle
Borrow the least specific type that still does the job: &str over &String, &[T] over &Vec<T>, &Path over &PathBuf. Owned types in arguments are for when the function actually needs to store the value. If it only reads, hand it the borrow — the caller keeps their allocation, and your function works with more types for free.