Could include_str!() accept a 'static &str instead of a string literal?

This is just a problem I’ve come across:

const CSS_PATH: &str = "C:\\my\\file\\path\\test.css";

#[cfg(debug_assertions)]
let css = Css::hot_reload(CSS_PATH).unwrap();

#[cfg(not(debug_assertions))]
let css = Css::new_from_str(include_str!(CSS_PATH)).unwrap();

This doesn’t compile in release mode, because include_str!() expects a string literal and doesn’t allow const strings - since include_str!() is built into the compiler, wouldn’t it be possible to allow this, since the compiler can already determine whether something is const or not?

It’s a minor issue, but it’s just that I wanted to avoid typing out the file path twice. Is there a way to do this or would it be possible to add this?

Curious - why do you need to use include_str! here? Any reason not to use the const in both places?

In debug mode, I need to reload the file from the harddrive, so I have to give it only the path to the file, but not the file itself, because the file will be hot-reloaded (from disk) - notice the Css::hot_reload() vs Css::new_from_str(). But in release mode, I want to include the file inside the binary.

Right now this is possible by doing:

#[cfg(debug_assertions)]
let css = Css::hot_reload("C:\\my\\file\\path\\test.css").unwrap();

#[cfg(not(debug_assertions))]
let css = Css::new_from_str(include_str!("C:\\my\\file\\path\\test.css")).unwrap();

… but then I have to update the path in two places.

Oh I see, I completely glossed over that.

Yeah, it’d be nice. I personally have a similar desire for the concat! macro, but include_str! is no different in this regard.

Looking at the source code for include_str!() it seems that it works on a syntax level, i.e. at this point in compilation, rustc doesn’t seem to have any information about whether a given str is const or not, which explains why concat, etc. don’t accept const strings.

Of course, it’s possible with a build script, but a build script is usually just a last line of defense. It would be a nice addition, but it’s probably going to require some refactoring in the compiler, so I’m going to file an issue in the rust repo, unless there is already a bug for it (haven’t seen one yet).

You can try using a macro that yields the hardcoded path (instead of a const), and call that macro from both places. It seems slightly hacky but ought to work for your purpose.

2 Likes

Yeah, that’s a good workaround - thanks for the suggestion. For now I’ve filed https://github.com/rust-lang/rust/issues/53749

Someone recently made a crate that implements this pattern for you https://crates.io/crates/load_file