In this lesson, you will learn how to design function signatures that minimize borrow constraints, making your code easier for others to use.
When you design an API, you decide exactly how much "permission" a function needs from the caller. If you write a function that demands a &mut String, you are forcing the user to have a mutable reference ready. However, if your function only needs to read the data, you should ask for a &String (or even better, a &str) instead. By being as specific as possible about the minimum required access, you prevent unnecessary borrow errors for your users.
Prefer Flexibility in Borrowing
Consider a function that prints the length of a string. If you write it like this:
fn print_length(s: &String) {
println!("{}", s.len());
}
You have created a rigid API. A user cannot pass a string literal (like "hello") to this function because "hello" is a &str, not a &String. To fix this, you should design your API to use the most general type possible:
fn print_length(s: &str) {
println!("{}", s.len());
}
Now, the user can pass a &String, a &str, or a string literal. By accepting &str instead of &String, you have reduced the constraint. The user no longer needs to convert their data to match your specific type requirements.
Apply the Principle of Least Privilege
The same logic applies to mutability. If you only need to modify a single field inside a struct, avoid requiring a mutable reference to the entire struct if possible. If you design your methods to take only the data they truly need, you allow the caller to borrow other parts of the same struct simultaneously.
Always ask: "Is this the least restrictive type I can use?" If you can replace a mutable reference with an immutable one, or a specific type with a more flexible reference, do it. This design philosophy prevents the "borrow checker dance" where your users struggle to satisfy your function signatures.
Key Takeaway: Design your APIs to require the least amount of permission necessary, favoring general reference types over specific ones to maximize flexibility for the caller.