Judging by your usage, I would say ident
is the correct choice. While other things like, path
, tt
, expr
may be appropriate for accepting a function in general, since you're only using it to create another identifier, ident
makes the most sense.
By way of sophisticated monte-carlo analysis, the way rust-analyzer seems to handle syntax detection in macros by expanding it first, assessing what code is generated, and then back-referencing that info to the original macro parameters.
In the following example, the decl_func1
call correctly links the function_name
identifier to the function definition, while decl_func2
call does not.
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);
}
So in your code, rust-analyzer won't make the connection to function_name
because the generated code only has function_name_x
.
A potential workaround would be to introduce a statement into the macro that would syntactically use the identifier as is, but in a way where it ultimately does nothing. This may be a good idea anyway so that the compiler, not just rust-analyzer, can verify the identifier is what it should be. A couple ideas:
// 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);