1 unstable release
new 0.10.0 | Nov 14, 2024 |
---|
#278 in Programming languages
106 downloads per month
13KB
161 lines
Make temporary values useable in a fairly normal style through macros. This nicely wraps the hacks that work around temporaries’ limitations. This crate is itself hopefully temporary, until Rust can natively solve the problem.
What Problem does this Solve?
Normally let str = &String::from("str");
shouldn’t compile. The inner String
object should be dropped at the end of
the statement, leaving a dangling reference. However, in simple cases like this, Rust gives you a pass, by extending the
lifetime. Alas this has not yet been generalised. You can often work around that, by storing the temporary value in a
separate variable.
The same situation arises, when the temporary value is hidden. Only, then you have no influence to work around it. This
is famously the case with format_args!
, the efficient alternative to heap-allocated format!
. This strongly limits
its usefulness – or did, without these macros!
Returning a temporary value from a simple block also benefits from lifetime extension. Again this is not yet the case
for more complex blocks, like if
or match
. Since Rust doesn’t have a ? :
operator, that prevents dynamic choice
involving temporaries. So, these fail to compile, showing both explicit and hidden temporaries in the 1st
case:
// `x` & `y` would live longer than the `String` and `format_args`’ hidden temporary.
let x = &vec![&String::from("x")];
let y = format_args!("1 + 2 = {}", 1 + 2);
// Consuming the value directly in `print!()` would be ok, were it not for the man in the middle, `if`.
print!("{}", if 1 < 1 {
format_args!("1 + 2 = {}", 1 + 2)
} else {
format_args!("1 + 3 = {}", 1 + 3)
});
The Solution
The let
problem is solved by turning it into a match
, making the value live as long as the following code. Multiple
choice is achieved by breaking from a tuple. Both of these are not nice to look at. Therefore temporaries
wraps them
up in convenient macros.
This only applies to local processing. Returning a temporary value from a closure or function is alas not something a
macro can achieve. That requires a language change, such as super let
, which is under discussion.
This was inspired by this &
this. There is a similar crate, which, unlike this one, needs a
proc-macro, hoist_temporaries
.