将ty转换为macro_rules中的标识



我有一个macro_rules,它接受function_name并调用function_name_x()。现在我通过传递function_name作为ident,并通过concat_idents!创建新的函数名来做到这一点。

这种方法的问题是我的IDE不检测function_name部分,因为它将其作为ident。我想将其更改为ty,但如果我这样做,我不能在concat_idents!中使用它。

有解决方案吗?

macro_rules! decl_func {
($env:expr, $func:ident) => {{
let f = concat_idents!($func, _to_ocaml);
let binding = f($env, None);
println!("{}", binding);
}};
}

根据您的使用情况,我认为ident是正确的选择。一般来说,pathttexpr可能适合接受一个函数,因为你只是用它来创建另一个标识符,而ident是最有意义的。


通过复杂的蒙特卡罗分析,rust-analyzer处理宏语法检测的方式似乎是首先展开宏,评估生成的代码,然后将该信息反向引用到原始宏参数。

在下面的示例中,decl_func1调用正确地将function_name标识符链接到函数定义,而decl_func2调用没有。

fn function_name() {}
macro_rules! decl_func1 {
($func:ident) => {
$func();
};
}
macro_rules! decl_func2 {
($func:ident) => {};
}
fn main() {
decl_func1!(function_name);
decl_func2!(function_name);
}

因此,在您的代码中,rust-analyzer不会连接到function_name,因为生成的代码只有function_name_x


一个潜在的解决方法是在宏中引入一条语句,该语句在语法上按原样使用标识符,但在某种程度上它最终什么也不做。无论如何,这可能是一个好主意,这样编译器(而不仅仅是rust-analyzer)可以验证标识符是否应该是什么。几个想法:

// would check that it is some kind of value
let _ = &$func;
// would check that it is a function with a signature that can take these types
let _ = || $func(1, 2);

相关内容

  • 没有找到相关文章

最新更新