rust - 在宏中调用 `stringify!`

标签 rust rust-macros

此宏在调用时编译:

macro_rules! remote_optional {
    ($remote:ident with=$def:ident $def_str:expr) => {
        impl $def {
            fn deserialize_option<'de, D>(deserializer: D) -> Result<Option<$remote>, D::Error>
            where
                D: Deserializer<'de>,
            {
                #[derive(Deserialize)]
                struct Wrapper(#[serde(with = $def_str)] $remote);

                let v: Option<Wrapper> = Option::deserialize(deserializer)?;
                Ok(v.map(|Wrapper(a)| a))
            }
        }
    }
}

这个没有:

macro_rules! remote_optional {
    ($remote:ident with=$def:ident) => {
        impl $def {
            fn deserialize_option<'de, D>(deserializer: D) -> Result<Option<$remote>, D::Error>
            where
                D: Deserializer<'de>,
            {
                #[derive(Deserialize)]
                struct Wrapper(#[serde(with = stringify!($def))] $remote);

                let v: Option<Wrapper> = Option::deserialize(deserializer)?;
                Ok(v.map(|Wrapper(a)| a))
            }
        }
    }
}

这是因为 stringify!($def) 被传递到 #[serde(...)] 属性未计算。

有什么实际的解决方法吗?

最佳答案

可以将两个参数的宏转发到三个参数的宏,扩展 def 标识符吗?

macro_rules! remote_optional {
    // The one that doesn't work (two arguments)
    // forwards to the one that *does* work, expanding the
    // string.
    ($remote:ident with=$def:ident) => {
        remote_optional!($remote, with=$def, stringify!($def));
    };

    // The macro that *does* work
    ($remote:ident with=$def:ident $def_str:expr) => {
        impl $def {
            fn deserialize_option<'de, D>(deserializer: D) -> Result<Option<$remote>, D::Error>
            where
                D: Deserializer<'de>,
            {
                #[derive(Deserialize)]
                struct Wrapper(#[serde(with = $def_str)] $remote);

                let v: Option<Wrapper> = Option::deserialize(deserializer)?;
                Ok(v.map(|Wrapper(a)| a))
            }
        }
    };
}

我们还可以考虑将三个参数的宏作为实现细节。

小的、孤立的概念验证:

macro_rules! my_macro {
    ($x:expr, $y:expr) => {
        my_macro!($x, $y, stringify!($x + $y));
    };

    ($x:expr, $y:expr, $msg:expr) => {
        println!("{} + {} = {}", $x, $y, $msg);
    };
}


fn main() {
    my_macro!(3, 2); // 3 + 2 = 3 + 2
}

关于rust - 在宏中调用 `stringify!`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55582838/

相关文章:

rust - 递归宏的困难

rust - 错误 : duplicate lang item in crate `sp_io`

rust - 解析rust proc_macro中括号内容

macros - 如何测试宏中的标识符是否以下划线开头?

build - 如何动态启用 crate 功能? [复制]

rust - 在Rust宏中将身份视为字符串

rust - 在过程宏中,如何检查字符串是否是有效的变量名而不是关键字?

rust - "Expecting a type here because of type ascription"

rust - 有没有办法在 actix-web 中拆分服务器路由声明?

segmentation-fault - 在实现两个段错误的类型上从特征 A 转换为特征 B