I had this problem multiple times now and wanted to ask this. Is there any smart possibility to do this without allocating a new string if condition() is false?
fn compile_error(mut s: &str) {
if condition() {
s = &format!("{}, condition was true", s)
}
// Do something with the string, this is just an example
println!("{}", s);
}
fn works_with_cloning(s: &str) {
let s = if condition() {
format!("{}, condition was true", s)
} else {
s.to_string() // I want to avoid this
};
// Do something with the string, this is just an example
println!("{}", s);
}
fn works(s: &str) {
let buf;
let s = if condition() {
buf = format!("{}, condition was true", s);
&buf
} else {
s
};
// Do something with the string, this is just an example
println!("{}", s);
}
Keep in mind that an &str is a reference to a string stored elsewhere (e.g. a local variable in the calling function). If you could swap out buf with another &str, who would own it once your function returns?
If you just want to swap it out within your function it's perfectly fine to use the Cow<str> trick mentioned by @alice, but if you want the caller to gain access to the string when the condition is true you'll need to come up with a different solution (e.g. returning the new string or passing in an &mut String).
fn works_without_cloning(s: &str) {
let s = if condition() {
format!("{}, condition was true", s).as_str() // Fixes your issue.
} else {
s // No Cloning
};
println!("{}", s);
}
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:4:9
|
3 | let s = if condition() {
| - borrow later stored here
4 | format!("{}, condition was true", s).as_str() // Fixes your issue.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
5 | } else {
| - temporary value is freed at the end of this statement
|
= note: consider using a `let` binding to create a longer lived value
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
The suggestion, consider using a `let` binding to create a longer lived value, is hinting at the solution @Hyeonu suggested.