Why can't this code compile:

const DEFAULT_SPEC_FILE: &str = "foobar";

fn foo() {
    let data = include_bytes!(DEFAULT_SPEC_FILE);
}

I think it is complaining that the input to include_bytes! is supposed to be a string constant. However, how much more can I make the string a constant?

As the error message says does include_bytes! want a string literal not a &'static str expression (other as the source code suggests). However, this is a built-in so I think the normal rules don’t apply here.

What you can do is using a simple macro:

macro_rules! foobar {
    () => {
        "foobar"
    };
}

const DEFAULT_SPEC_FILE: &str = foobar!();

fn foo() {
    let data = include_bytes!(foobar!());
}
1 Like

Clever use of macros. Thanks!

For this kind of stuff I like the following kind of macro:

macro_rules! string_constants {(
    $(
        $pub:vis
        const $CONST_NAME:ident : & $('static)? str = $string:expr ;
    )*
) => (
    $(
        $pub
        const $CONST_NAME: &'static str = $string;
    
        macro_rules! $CONST_NAME {() => ($string)}
    )*
)}

and you can then use it like follows:

string_constants! {
    const FOO: &str = "Foo";
    const BAR: &str = "Bar";
}

in order to create not only these constants but also the “macrofied” versions of them: FOO!() and BAR!(), usable within other macros that expect string literals :slight_smile:. For instance,

string_constants! {
    const FOO: &str = "Foo";
    const BAR: &str = "Bar";
    const FOOBAR: &str = concat!(FOO!(), BAR!());
}
3 Likes