From ae199d0217ec89f36ab75936ce56fc3db032e079 Mon Sep 17 00:00:00 2001 From: myrrlyn Date: Sun, 16 Feb 2020 20:56:56 -0700 Subject: [PATCH] Permit trailing commas in macro invocations This commit uses the `?` operator to support optional trailing commas in macro calls without requiring the call to use the panic-message arms. The `?` macro operator was stabilized in `1.32` for the 2018 edition, and `1.37` for the 2015 edition. Applying this commit requires raising the crate MSRV to one of these two versions; for the lower, the crate must be explicitly set to the `edition = "2018"` key in its manifest. --- src/lib.rs | 55 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0c3d5b5..8dd930d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ /// assert_matches!(a, Foo::A(i) if i > 0); /// /// let b = Foo::B("foobar"); -/// +/// /// // Assert that `b` matches the pattern `Foo::B(_)`. /// assert_matches!(b, Foo::B(s) => { /// // Perform additional assertions on the variable binding `s`. @@ -60,60 +60,60 @@ /// ``` #[macro_export] macro_rules! assert_matches { - ( $e:expr , $pat:pat ) => { + ( $e:expr , $pat:pat $(,)? ) => { match $e { $pat => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($pat)) } }; - ( $e:expr , $pat:pat if $cond:expr ) => { + ( $e:expr , $pat:pat if $cond:expr $(,)? ) => { match $e { $pat if $cond => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($pat if $cond)) } }; - ( $e:expr , $pat:pat => $arm:expr ) => { + ( $e:expr , $pat:pat => $arm:expr $(,)? ) => { match $e { $pat => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($pat)) } }; - ( $e:expr , $pat:pat if $cond:expr => $arm:expr ) => { + ( $e:expr , $pat:pat if $cond:expr => $arm:expr $(,)? ) => { match $e { $pat if $cond => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($pat if $cond)) } }; - ( $e:expr , $pat:pat , $($arg:tt)* ) => { + ( $e:expr , $pat:pat , $($arg:tt)+ ) => { match $e { $pat => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", - e, stringify!($pat), format_args!($($arg)*)) + e, stringify!($pat), format_args!($($arg)+)) } }; - ( $e:expr , $pat:pat if $cond:expr , $($arg:tt)* ) => { + ( $e:expr , $pat:pat if $cond:expr , $($arg:tt)+ ) => { match $e { $pat if $cond => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", - e, stringify!($pat if $cond), format_args!($($arg)*)) + e, stringify!($pat if $cond), format_args!($($arg)+)) } }; - ( $e:expr , $pat:pat => $arm:expr , $($arg:tt)* ) => { + ( $e:expr , $pat:pat => $arm:expr , $($arg:tt)+ ) => { match $e { $pat => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", - e, stringify!($pat), format_args!($($arg)*)) + e, stringify!($pat), format_args!($($arg)+)) } }; - ( $e:expr , $pat:pat if $cond:expr => $arm:expr , $($arg:tt)* ) => { + ( $e:expr , $pat:pat if $cond:expr => $arm:expr , $($arg:tt)+ ) => { match $e { $pat if $cond => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", - e, stringify!($pat if $cond), format_args!($($arg)*)) + e, stringify!($pat if $cond), format_args!($($arg)+)) } }; } @@ -302,4 +302,33 @@ mod test { assert_matches!(a, Foo::B(s) if s == "foo" => {}, "msg"); }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`: msg"#); } + + #[test] + fn trailing_commas() { + let a = Foo::A(123); + + assert_matches!(a, Foo::A(..)); + assert_matches!(a, Foo::A(..),); + + assert_matches!(a, Foo::A(val) if val >= 100); + assert_matches!(a, Foo::A(val) if val >= 100,); + + assert_matches!(a, Foo::A(val) => assert!(val >= 100)); + assert_matches!(a, Foo::A(val) => assert!(val >= 100),); + + assert_matches!(a, Foo::A(val) if val >= 100 => assert!(val < 200)); + assert_matches!(a, Foo::A(val) if val >= 100 => assert!(val < 200),); + + assert_matches!(a, Foo::A(..), "error message"); + assert_matches!(a, Foo::A(..), "error message",); + + assert_matches!(a, Foo::A(val) if val >= 100, "error message"); + assert_matches!(a, Foo::A(val) if val >= 100, "error message",); + + assert_matches!(a, Foo::A(val) => assert!(val >= 100), "error message"); + assert_matches!(a, Foo::A(val) => assert!(val >= 100), "error message",); + + assert_matches!(a, Foo::A(val) if val >= 100 => assert!(val < 200), "error message"); + assert_matches!(a, Foo::A(val) if val >= 100 => assert!(val < 200), "error message",); + } }