Help with understanding print!() with string literal

i am not able to understand why

    let s = "hello";
    print!("{}", s);

works but not this:

    let s = "hello";
    print!(s);

s is storing a string literal according to my understanding. the same thing works well in C's printf() but not working here.

can anyone help me in this regard?

thank you.

1 Like

it's because, print! is a macro, not a function. and it requires the format string to be a literal known at compile time.

3 Likes

No, it doesn't. It stores a &'static str. The string literal is the thing with the double quotes (including those) and only exists at compile time.

2 Likes

i almost got that understanding but i was not really sure. Thank you for the clarification

To expand a bit, you can write your own macros that only accept literals (playground):

macro_rules! takes_literal {
    ($foo:literal) => { dbg!($foo); }
}

fn main() {
    takes_literal!("foo"); // [src/main.rs:7:5] "foo" = "foo"

    let foo = "foo";
    takes_literal!(foo);   // does not compile

    const FOO: &str = "foo";
    takes_literal!(FOO);   // does not compile either
}

although it's not possible to implement a print-like macro from scratch yourself, as it needs compiler support to parse and validate the format string.

3 Likes

although it's not possible to implement a print-like macro from scratch yourself, as it needs compiler support to parse and validate the format string.

Sorry to nitpick, but the format_args! macro is available if you need to format "hello {a} {:2}" style strings. println! expands to include format_args!, though format_args! itself is a compiler builtin.

And if you need to parse a more complex syntax, you can use a proc macro which can perform completely arbitrary transformations to your Rust code.

Which is why I said "from scratch" :slight_smile: As in, without using the compiler-provided formatting machinery.