From f39ec89ca0d4522e89cbfcf73fee33615dc934bf Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 9 Sep 2020 19:38:05 -0400 Subject: [PATCH] Turn block into a closure in test macro The `doc_test!` macro defines two local variables (`entries` and `doc`), which are then accessed from the provided `block`. However, this only compiled due to a bug in rustc: substituted metavariables cannot refer to names defined within the macro body. For example, the following ode does not compile: ```rust macro_rules! foo { ($block:expr) => { let mut bar = false; $block } } fn main() { foo!({bar = true}); } ``` In this case, the `doc_test!` macro was incorrectly allowed to compile due to the presence of the `#[tokio::test]` macro on the enclosing function. When the underlying compiler bug is fixed in https://github.com/rust-lang/rust/pull/75800, this macro will stop compiling. I've adjusted the macro to take in a closure instead of a block. This closure is invoked with the `entries` and `doc` variables, allowing it to compile with both old and new compilers. If you have any questions about this change, feel free to ask me. --- src/tests.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index ea9001f7..46fc715e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -56,15 +56,15 @@ impl DocFileLoader for TestLoader { } macro_rules! doc_test { - ( $name:ident, $source:expr; $block:block ) => { + ( $name:ident, $source:expr; $block:expr ) => { doc_test!($name, $source, false; $block); }; - ( $name:ident, $source:expr, private; $block:block ) => { + ( $name:ident, $source:expr, private; $block:expr ) => { doc_test!($name, $source, true; $block); }; - ( $name:ident, $source:expr, $private:expr; $block:block ) => { + ( $name:ident, $source:expr, $private:expr; $block:expr ) => { #[tokio::test] async fn $name() { use swc_ecmascript::parser::Syntax; @@ -83,7 +83,8 @@ macro_rules! doc_test { #[allow(unused_variables)] let doc = DocPrinter::new(&entries, false, private).to_string(); - $block + #[allow(clippy::redundant_closure_call)] + ($block)(entries, doc) } }; } @@ -101,7 +102,7 @@ macro_rules! contains_test { ( $name:ident, $source:expr, $private:expr; $( $contains:expr ),* $( ; $( $notcontains:expr ),* )? ) => { - doc_test!($name, $source, $private; { + doc_test!($name, $source, $private; |_entries, doc: String| { $( assert!(doc.contains($contains)); )* @@ -124,7 +125,7 @@ macro_rules! json_test { }; ( $name:ident, $source:expr, $private:expr; $json:tt ) => { - doc_test!($name, $source, $private; { + doc_test!($name, $source, $private; |entries, _doc| { let actual = serde_json::to_value(&entries).unwrap(); let expected_json = json!($json); assert_eq!(actual, expected_json);