Crates.io | temporaries |
lib.rs | temporaries |
version | |
source | src |
created_at | 2024-11-14 10:26:40.188506 |
updated_at | 2025-01-21 22:34:31.435794 |
description | Make temporary values useable in a fairly normal style through macros. This nicely wraps the hacks that work around temporaries’ limitations. |
homepage | |
repository | https://sourceforge.net/p/temporaries/ |
max_upload_size | |
id | 1447644 |
Cargo.toml error: | TOML parse error at line 19, column 1 | 19 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
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.
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
.