This code compiles in older versions of Rust, but after updating to 1.79.0 I get this error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:2:10
|
2 | Some(include_dir::include_dir!("$CARGO_MANIFEST_DIR/assets"))
| -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
| | |
| | creates a temporary value which is freed while still in use
| using this value as a static requires that borrow lasts for `'static`
3 | } else {
| - temporary value is freed at the end of this statement
|
= note: this error originates in the macro `include_dir::include_dir` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0716`.
I imagine the issue is related to the if statement because this compiles without any issues in 1.79.0:
Strangely enough, #121346 looks like it should've made this start successfully compiling, not stop, although AIUI it shouldn't've compiled successfully before nor after the change... outside of a constant initializer context, anyway; IIRC such contexts change how promotion works and are supposed to promote to &'static instead of &'let.
This is probably what you would prefer anyway, since this means include_dir! won't happen for non-wasm builds, whereas just using if cfg! still expands the include_dir! macro.
Since I went ahead and did the initial look into what's going on, I went ahead and filed a regression issue.
It looks like this is #121557 instead, which deliberately restricts promotion of const fn calls. That also indicates another potential successful rewrite:
pub static ASSETS_DIR: Option<include_dir::Dir<'_>> = {
let it = include_dir::include_dir!("$CARGO_MANIFEST_DIR/assets");
if cfg!(target_arch = "wasm32") {
Some(it)
} else {
None
}
}
If you want something to be const-promoted, then it's much better to just tell the compiler explicitly. Having the compiler implicitly promote function calls is problematic for the reasons explained in this RFC.
For this specific case, I'd agree that two separate #[cfg(..)]'d declarations (or perahps cfg_if) is probably better (since it won't even evaluate the include_dir! when cfg'd out).
Note that const { ... } expressions are not available on Rust <= 1.79.0 (and you can't rewrite the output of the include_dir! macro yourself to include one anyway).
If others have a similar issue which is not adequately solved by the #[cfg(..)] solution (e.g. if the conditional is an more complicated expression based on not just a cfg!), a workaround that works on versions 1.78.0 and 1.79.0 is to put the include_dir invocation unconditionally into a separate const item which will be promoted/checked separately, e.g.
Yeah, that's the backwards-compatible way, but unfortunately it still relies on implicit promotion of File::new -- something rustc should never have accepted and something we might try to phase out eventually, over an edition or so.
Given that the last commit to that repo was 2 years ago, I'm doubtful anything will happen. Looking at open and closed issues I also don't think anything will happen.