Here's my Rust 101 rules for this:
-
"
&str
for parameters;String
for return types". This always works, and has no borrowck complications, but is sometimes inefficient. -
the small tweak to add "If you always need to
to_owned
/to_string
the&str
parameter, change it to aString
parameter". That's more efficient when your caller happens to already have aString
, no less efficient if they don't, and still doesn't require thinking about lifetimes. -
if you're always returning a substring of one of the arguments, add a lifetime generic and return a
&'a str
, updating the corresponding parameter from&str
to&'a str
as well.
That covers the vast majority of cases, but there are of course more complicated scenarios that need something fancier.