| 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.