1#[macro_export]
40macro_rules! assert_matches {
41 ($expression:expr, $($pattern:pat)|+ $(if $guard:expr)? $(,)?) => {
42 #[allow(unreachable_patterns)]
43 match $expression {
44 $($pattern)|+ $(if $guard)? => {},
45 other => {
46 ::core::panic!(r#"assertion failed, expression does not match the given pattern.
47 expression: {:?}
48 pattern: {}"#, other, ::core::stringify!($($pattern)|+ $(if $guard)?));
49 }
50 }
51 };
52 ($expression:expr, $($pattern:pat)|+ $(if $guard:expr)?, $($arg:tt)+) => {
53 #[allow(unreachable_patterns)]
54 match $expression {
55 $($pattern)|+ $(if $guard)? => {},
56 other => {
57 ::core::panic!(r#"assertion failed, expression does not match the given pattern.
58 expression: {:?}
59 pattern: {}: {}"#, other, ::core::stringify!($($pattern)|+ $(if $guard)?), ::core::format_args!($($arg)+));
60 }
61 }
62 };
63}
64
65#[macro_export]
71macro_rules! debug_assert_matches {
72 ($($arg:tt)*) => {
73 #[cfg(debug_assertions)]
74 $crate::assert_matches!($($arg)*);
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 #[allow(dead_code)]
81 #[derive(Debug)]
82 enum Foo {
83 Bar(usize),
84 Baz(usize),
85 }
86
87 #[test]
88 fn matches() {
89 assert_matches!(Foo::Bar(42), Foo::Bar(_));
90 }
91
92 #[test]
93 fn matches_multiple_variants() {
94 assert_matches!(Foo::Baz(42), Foo::Bar(_) | Foo::Baz(_));
95 }
96
97 #[test]
98 #[should_panic(
99 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Baz(_)"
100 )]
101 fn not_matches() {
102 assert_matches!(Foo::Bar(42), Foo::Baz(_));
103 }
104
105 #[test]
106 #[should_panic(
107 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Baz(_): foo"
108 )]
109 fn not_matches_custom_message() {
110 assert_matches!(Foo::Bar(42), Foo::Baz(_), "foo");
111 }
112
113 #[test]
114 fn matches_if_guard() {
115 assert_matches!(Foo::Bar(42), Foo::Bar(x) if x < 100);
116 }
117
118 #[test]
119 #[should_panic(
120 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Bar(x) if x > 100"
121 )]
122 fn not_matches_if_guard() {
123 assert_matches!(Foo::Bar(42), Foo::Bar(x) if x > 100);
124 }
125
126 #[test]
127 #[should_panic(
128 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Bar(x) if x > 100: foo"
129 )]
130 fn not_matches_if_guard_custom_message() {
131 assert_matches!(Foo::Bar(42), Foo::Bar(x) if x > 100, "foo");
132 }
133
134 #[rustversion::since(1.53)]
135 #[test]
136 fn matches_nested_pattern() {
137 assert_matches!(Some(Foo::Bar(42)), Some(Foo::Bar(_) | Foo::Baz(1 | 2)));
138 }
139
140 #[rustversion::since(1.53)]
141 #[test]
142 #[should_panic(
143 expected = "assertion failed, expression does not match the given pattern.\n expression: None\n pattern: Some(Foo::Bar(_) | Foo::Baz(1 | 2))"
144 )]
145 fn not_matches_nested_pattern() {
146 assert_matches!(None, Some(Foo::Bar(_) | Foo::Baz(1 | 2)));
147 }
148
149 #[test]
150 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
151 fn debug_matches() {
152 debug_assert_matches!(Foo::Bar(42), Foo::Bar(_));
153 }
154
155 #[test]
156 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
157 fn debug_matches_multiple_variants() {
158 debug_assert_matches!(Foo::Baz(42), Foo::Bar(_) | Foo::Baz(_));
159 }
160
161 #[test]
162 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
163 #[should_panic(
164 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Baz(_)"
165 )]
166 fn debug_not_matches() {
167 debug_assert_matches!(Foo::Bar(42), Foo::Baz(_));
168 }
169
170 #[test]
171 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
172 #[should_panic(
173 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Baz(_): foo"
174 )]
175 fn debug_not_matches_custom_message() {
176 debug_assert_matches!(Foo::Bar(42), Foo::Baz(_), "foo");
177 }
178
179 #[test]
180 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
181 fn debug_matches_if_guard() {
182 debug_assert_matches!(Foo::Bar(42), Foo::Bar(x) if x < 100);
183 }
184
185 #[test]
186 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
187 #[should_panic(
188 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Bar(x) if x > 100"
189 )]
190 fn debug_not_matches_if_guard() {
191 debug_assert_matches!(Foo::Bar(42), Foo::Bar(x) if x > 100);
192 }
193
194 #[test]
195 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
196 #[should_panic(
197 expected = "assertion failed, expression does not match the given pattern.\n expression: Bar(42)\n pattern: Foo::Bar(x) if x > 100: foo"
198 )]
199 fn debug_not_matches_if_guard_custom_message() {
200 debug_assert_matches!(Foo::Bar(42), Foo::Bar(x) if x > 100, "foo");
201 }
202
203 #[rustversion::since(1.53)]
204 #[test]
205 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
206 fn debug_matches_nested_pattern() {
207 debug_assert_matches!(Some(Foo::Bar(42)), Some(Foo::Bar(_) | Foo::Baz(1 | 2)));
208 }
209
210 #[rustversion::since(1.53)]
211 #[test]
212 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
213 #[should_panic(
214 expected = "assertion failed, expression does not match the given pattern.\n expression: None\n pattern: Some(Foo::Bar(_) | Foo::Baz(1 | 2))"
215 )]
216 fn debug_not_matches_nested_pattern() {
217 debug_assert_matches!(None, Some(Foo::Bar(_) | Foo::Baz(1 | 2)));
218 }
219
220 #[test]
221 #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
222 fn debug_release_not_matches() {
223 debug_assert_matches!(Foo::Bar(42), Foo::Baz(_));
224 }
225
226 #[test]
227 #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
228 fn debug_release_not_matches_if_guard() {
229 debug_assert_matches!(Foo::Bar(42), Foo::Bar(x) if x > 100);
230 }
231
232 #[rustversion::since(1.53)]
233 #[test]
234 #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
235 fn debug_release_not_matches_nested_pattern() {
236 debug_assert_matches!(None, Some(Foo::Bar(_) | Foo::Baz(1 | 2)));
237 }
238}