ruststring-literalsrust-macros

Rust Macro: Expected literal


I'm learning macro's a bit and trying to use them to easily export my stuff into the right directory. export_to expects a string literal, and i thought that's what concat does but apparently it's not so clear. Is this a limitation with macro's? Or is there some solution to this?

The macro expansion seems to work just fine, so i don't know what's going on.

Any tips or ideas would be much appreciated!

#[macro_export]
macro_rules! create_endpoint {
    ($route:expr, $method:expr, $in_t:ty, $out_t:ty ) => {
        #[derive(Clone, Debug, Serialize, Deserialize, TS)]
        #[ts(export, export_to = concat!("../src/lib/endpoint_defines/", $route, "/", $method, ".ts"))]
        struct __Endpoint {
          in_type: $in_t,
          out_data_type: $out_t
        }
        
        #[cfg(test)]
        #[test]
        fn __export_write_endpoint() {
          write_endpoint($method, $route);
        }
    };
}
error: expected literal
  --> src/handshake/endpoint.rs:13:34
   |
13 |         #[ts(export, export_to = concat!("../src/lib/endpoint_defines/", $route, "/", $method, ".ts"))]
   |                                  ^^^^^^
   |
  ::: src/routes/mod.rs:18:1
   |
18 | create_endpoint!("", "POST", (), ());
   | ------------------------------------ in this macro invocation
   |
   = note: this error originates in the macro `create_endpoint` (in Nightly builds, run with -Z macro-backtrace for more info)

Solution

  • Assuming you don't control the TS macro and cannot change it, this is indeed a problem. If the macro expects a literal, somethings that expands to a literal (e.g. concat!() won't work.

    Declarative macros (macro_rules!) cannot solve this on their own. If you want to stick with them, you'll have to pass the whole string to the macro, which is unfortunate.

    Procedural macros, however, can be of help, since they are able to concatenate literals by themselves, thus pass a ready literal to TS. It might be possible to use an existing crate for that, though I couldn't find any.