&new_string()
should be valid in the exact same situations where new_string().as_ref()
is - neither has special rules. If I recall correctly, the temporary will stay alive for the entire statement, but not longer than that.
By that I mean, as long as do_something
has no particular lifetime requirements on the &str
it consumes, even this is valid:
do_something(format!("a {} string", "new").as_str());
By that I mean that this compiles in playground:
fn do_something(v: &str) {}
fn main() {
do_something(format!("a {} string", "new").as_str());
}
So if there were extra restrictions on the lifetime do_something
can accept that would cause the example in the OP to fail, then do_something(&format!(""))
would fail as well.
Responding to the OP, I think something similar to what you're suggesting already happens - it just isn't as broad. Rather than transforming your code into
let text: String = expression_that_creates_string;
do_something(text.as_str());
Rust transforms it into
{
let text: String = expression_that_creates_string;
do_something(text.as_str())
};
The temporary is guaranteed to live as long as the statement, but it lives only that long, not as long as the entire block the statement is in.
As others have stated, this is preferable in general, and allows much nicer usage with mutexes and such. For instance, how long would you expect this code to hold the mutex for?
let x = calc_a;
mutex.lock().insert(x);
let y = calc_b;
Under rust's current rules, mutex
is unlocked directly before the let y = ...
line. If we went with your suggestion instead, then mutex
would remain locked through calc_b
- I'd argue the confusion in this case wouldn't be worth the extra simplicity when dealing with things like strings.
There could be a way around that - only extending the drop if the lifetime required it. I think this would probably also be bad, though, since it'd become even harder to analyze the behavior of any particular code segment. In addition, all valid rust code can currently be compiled without understanding lifetime bounds - breaking that for ergonomics probably wouldn't be a good idea?
Hope that wasn't overly harsh! I think looking for ways to improve the way rust handles things is good, but there are a lot of pitfalls when dealing with drop rules. Plus, as CAD97 pointed out, these rules are stable. Changing the drop order so that intermediate values are kept longer could and would break code.