Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering macro argument execution

Tags:

macros

rust

I'm using a library for string interning (string-cache), that uses macros to efficient create elements (atom!). However for simplification here is a similar macro that demonstrates the problem

macro_rules! string_intern {
   ("d") => ("Found D");
}

say I need to call this macro from another macro and give it a string version of an identifier.

macro_rules! print_ident {
    ($id:ident) => (
        string_intern!(stringify!($id));
    );
}

However calling this macro

fn main() {
    print_ident!(d);
}

Fails with error:

error: no rules expected the token `stringify`
 --> <anon>:7:24
  |
7 |         string_intern!(stringify!($id));
  |                        ^^^^^^^^^

Playground link

I know stringify! correctly converts to identifier d to string "d", because giving it to println! works as expected. Is there a way to pass the identifier I want turned into string to string_intern?

like image 587
Daniel Fath Avatar asked Jan 05 '23 06:01

Daniel Fath


1 Answers

println! lets you do this because it uses format_args! under the covers, which is a compiler-provided "intrinsic" that forcibly evaluates its first argument before using it. You cannot do this from a user-defined macro; you'd have to write a compiler plugin (which requires a nightly compiler and no guarantee of stability).

So, yeah; you can't. Sorry. The only thing you can do is redefine the macro in such a way that you don't need an actual string literal, or change how you invoke it.

like image 139
DK. Avatar answered Jan 07 '23 21:01

DK.