Macro_metavar_expr_concat not working as concat_idents

Hi,

I just updated nightly and noted that concat_idents! is no longer ok for use. I've tried to migrate to the new macro_metavar_expr_concat but struggling to make it work.

I used to have the following macro for generating methods calling the underlying assembly methods in the Sleef library:

macro_rules! im_simd_f {
    ($i:ident,$( $x:ident ),* ) => {
        #[inline(always)]
        fn $i(self) -> Self {Self(unsafe { concat_idents!(Sleef_, $($x,)*)(self.0.into()) }.into())}
    };
}


// For example called as the following for the exp_m1 function (for a 16 lane type):
im_simd_f!(exp_m1, expm1, f16, _u10);

However, trying to do the same thing with the new concat(..):


#[cfg(target_os = "windows")]
macro_rules! im_simd_f {
    ($i:ident,$( $x:ident ),* ) => {
        #[inline(always)]
        fn $i(self) -> Self {Self(unsafe {  ${concat(Sleef_, $($x,)*)} (self.0.into()) }.into())}
    };
}

I seem unable to escape the compiler errors messages:


error: expected identifier or string literal
  --> ad\src\macros.rs:78:63
   |
78 |         fn $i(self) -> Self {Self(unsafe {  ${concat(Sleef_, $($x,)*)} (self.0.into()) }.into())}
   |                                                               ^^^^^


Does anyone have any pointers here?

Regards

I think you can report a bug.

to my understanding, this is not currently supported by the meta variable expression mechanism. unlike the old concat_ident!() which is parsed, syntactically, just like an macro, a meta variable expression is parsed and processed somewhat "eagerly".

I think the compile error you see was not even caused by code after macro expansion, code probably cannot be parsed as a valid macro defintion in the first place.

still, I think your code is a valid use case that should be supported, you should definitely send your feedback, either as a feature request, or maybe just comment in the tracking issue for #![feature(macro_metavar_expr_concat)].

that said, relying on unstable features in your project is not a good bet. if there are no alternatives, you may want to pin down the toolchain to a specific nightly version, e.g. with a rust-toolchain.toml configuration. but in the case of concat_ident!(), there are actually stable alternatives using procedural macros, the most popular being paste.

Thanks,

Will check out paste.

Reported: Tracking Issue for `macro_metavar_expr_concat` · Issue #124225 · rust-lang/rust · GitHub

Incidentally I've recently released a library for doing things like that.

With it your example would look like this:

use compose_idents::compose_item;

macro_rules! im_simd_f {
    ($i:ident, $( $x:ident ),* ) => {
        #[compose_item(
            // Build the callee like: Sleef_expm1f16_u10
            callee = concat(Sleef, _, $( $x ),*),
        )]
        #[inline(always)]
        fn $i(self) -> Self {
            // `callee` identifier now serves as a template placeholder.
            Self(unsafe { callee(self.0.into()) }.into())
        }
    };
}

// Example:
// generates `fn exp_m1(self) -> Self` that calls `Sleef_expm1f16_u10(...)`
im_simd_f!(exp_m1, expm1, f16, _u10);

Or like this:

use compose_idents::compose;

macro_rules! im_simd_f {
    ($i:ident, $( $x:ident ),* ) => {
        compose!(
            // Build the callee like: Sleef_expm1f16_u10
            callee = concat(Sleef_, $( $x ),*),
            {
                #[inline(always)]
                fn $i(self) -> Self {
                    // `callee` identifier now serves as a template placeholder.
                    Self(unsafe { callee(self.0.into()) }.into())
                }
            }
        );
    };
}

// Example:
// generates `fn exp_m1(self) -> Self` that calls `Sleef_expm1f16_u10(...)`
im_simd_f!(exp_m1, expm1, f16, _u10);

https://github.com/AndreiPashkin/compose-idents

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.