Crates.io | temporaries |
lib.rs | temporaries |
version | 0.10.5 |
created_at | 2024-11-14 10:26:40.188506+00 |
updated_at | 2025-08-20 14:21:18.094814+00 |
description | Make temporary values useable in a fairly normal style through macros. This nicely wraps the hacks that work around temporaries’ earlier limitations. |
homepage | |
repository | https://sourceforge.net/p/temporaries/ |
max_upload_size | |
id | 1447644 |
size | 13,637 |
Make temporary values useable in a fairly normal style through macros. This nicely wraps the hacks that work around temporaries’ earlier limitations.
[!NOTE] Rust 1.89 has mostly solved these problems. That makes this crate far less useful going forward. Furthermore Edition 2024 had already closed the wormhole magically allowing
if_workaround
. This still works on newer compilers, but only if the calling code remains on an older Edition.
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, even in edition 2024 these fail to compile. I’m 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 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.
Actually if_workaround
should parse an if
statement, but (with sane effort) that is not possible. While if
statements put a block after an expression, macro rules oddly do not permit to express this normal Rust syntax.
This was inspired by this &
this. There is a similar crate, which, unlike this one, needs a
proc-macro, hoist_temporaries
.