Cross posting with tokio issue tracker.
I know how to work around this (can put parens around the macro variable: ($foo_factory)()), but I don't think this should be happening in the first place. Feels like a bug in the macro system. This is reproducible in the playground:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fb6d73cfb878547b438d8ec49431a4d2
concrete_tests2 and concrete_tests3 compile whereas concrete_tests1 does not.
I'm producing a declarative macro that takes in an expr that is meant to be a closure, and produces a #[tokio::test] that invokes that closure. The compile error is:
error[E0618]: expected function, found `Concrete`
--> src/lib.rs:38:32
|
14 | $crate::test_suite::async_test($foo_factory()).await;
| -- call expression requires function
...
38 | crate::use_test_suite!( || crate::Concrete::default() );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
The code (from the playground link above) is:
// /////////////////////////
// Define a trait Foo
// /////////////////////////
pub trait Foo{}
// /////////////////////////
// Define a test suite suitable for any implementator of Foo
// /////////////////////////
#[macro_export]
macro_rules! use_test_suite {
($foo_factory:expr) => {
#[tokio::test]
async fn async_test() {
$crate::test_suite::async_test($foo_factory()).await;
}
#[test]
fn sync_test() {
$crate::test_suite::sync_test($foo_factory());
}
}
}
pub mod test_suite {
pub async fn async_test(_foo: impl crate::Foo) -> u8 { 0 }
pub fn sync_test(_foo: impl crate::Foo) -> u8 { 0 }
}
// /////////////////////////
// Define an implementaion of Foo and test it
// /////////////////////////
#[derive(Default)]
struct Concrete;
impl Foo for Concrete {}
#[cfg(test)]
mod concrete_tests1 {
crate::use_test_suite!( || crate::Concrete::default() );
}
#[cfg(test)]
mod concrete_tests2 {
crate::use_test_suite!( (|| crate::Concrete::default()) );
}
#[cfg(test)]
mod concrete_tests3 {
crate::use_test_suite!( crate::Concrete::default );
}
Cross posting with tokio issue tracker.
I know how to work around this (can put parens around the macro variable:
($foo_factory)()), but I don't think this should be happening in the first place. Feels like a bug in the macro system. This is reproducible in the playground:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fb6d73cfb878547b438d8ec49431a4d2
concrete_tests2andconcrete_tests3compile whereasconcrete_tests1does not.I'm producing a declarative macro that takes in an
exprthat is meant to be a closure, and produces a#[tokio::test]that invokes that closure. The compile error is:The code (from the playground link above) is: