@@ -167,43 +167,70 @@ fn parse_tuple_pattern_args(
167
167
let ( patterns, dot_dot) =
168
168
parse_list_terminated_pattern :: < MaybeTupleFieldPattern > . parse2 ( group_content) ?;
169
169
let field_count = patterns. len ( ) ;
170
- let field_patterns = patterns
170
+ let field_patterns: Vec < _ > = patterns
171
171
. into_iter ( )
172
172
. enumerate ( )
173
173
. filter_map ( |( index, maybe_pattern) | maybe_pattern. 0 . map ( |pattern| ( index, pattern) ) )
174
174
. map ( |( index, TupleFieldPattern { ref_token, matcher } ) | {
175
175
let index = syn:: Index :: from ( index) ;
176
176
quote ! { googletest:: matchers:: field!( #struct_name. #index, #ref_token #matcher) }
177
- } ) ;
177
+ } )
178
+ . collect ( ) ;
178
179
179
- let matcher = quote ! {
180
- googletest:: matchers:: __internal_unstable_do_not_depend_on_these:: is(
181
- stringify!( #struct_name) ,
182
- all!( #( #field_patterns) , * )
183
- )
184
- } ;
180
+ if field_patterns. is_empty ( ) {
181
+ // It is possible that the logic above didn't generate any field matchers
182
+ // (e.g., for patterns like `Some(_)`).
183
+ // In this case we verify that the enum has the correct case, but don't
184
+ // verify the payload.
185
+ #[ allow( clippy:: manual_repeat_n) ]
186
+ // `repeat_n` is not available on the Rust MSRV that we support in OSS
187
+ let ignored_fields = std:: iter:: repeat ( quote ! { _ } )
188
+ . take ( field_count)
189
+ . chain ( dot_dot. map ( ToTokens :: into_token_stream) ) ;
190
+ let full_pattern = quote ! { #struct_name ( #( #ignored_fields) , * ) } ;
185
191
186
- // Do a match to ensure:
187
- // - Fields are exhaustively listed unless the pattern ended with `..`.
188
- // - `UNDEFINED_SYMBOL(..)` fails to compile.
189
- let empty_fields = std:: iter:: repeat ( quote ! { _ } )
190
- . take ( field_count)
191
- . chain ( dot_dot. map ( ToTokens :: into_token_stream) ) ;
192
- Ok ( quote ! {
193
- googletest:: matchers:: __internal_unstable_do_not_depend_on_these:: compile_assert_and_match(
194
- |actual| {
195
- // Exhaustively check that all field names are specified.
196
- match actual {
197
- #struct_name ( #( #empty_fields) , * ) => ( ) ,
198
- // The pattern below is unreachable if the type is a struct (as opposed to
199
- // an enum). Since the macro can't know which it is, we always include it
200
- // and just tell the compiler not to complain.
201
- #[ allow( unreachable_patterns) ]
202
- _ => { } ,
203
- }
204
- } ,
205
- #matcher)
206
- } )
192
+ Ok ( quote ! {
193
+ googletest:: matchers:: __internal_unstable_do_not_depend_on_these:: pattern_only(
194
+ |actual| { matches!( actual, #full_pattern) } ,
195
+ concat!( "is " , stringify!( #full_pattern) ) ,
196
+ concat!( "is not " , stringify!( #full_pattern) )
197
+ )
198
+ } )
199
+ } else {
200
+ // We have created at least one field matcher. Each field matcher will verify
201
+ // not only its part of the payload, but also that the enum has the
202
+ // correct case.
203
+ let matcher = quote ! {
204
+ googletest:: matchers:: __internal_unstable_do_not_depend_on_these:: is(
205
+ stringify!( #struct_name) ,
206
+ all!( #( #field_patterns) , * )
207
+ )
208
+ } ;
209
+
210
+ // Do a match to ensure:
211
+ // - Fields are exhaustively listed unless the pattern ended with `..`.
212
+ // - `UNDEFINED_SYMBOL(..)` fails to compile.
213
+ #[ allow( clippy:: manual_repeat_n) ]
214
+ // `repeat_n` is not available on the Rust MSRV that we support in OSS
215
+ let empty_fields = std:: iter:: repeat ( quote ! { _ } )
216
+ . take ( field_count)
217
+ . chain ( dot_dot. map ( ToTokens :: into_token_stream) ) ;
218
+ Ok ( quote ! {
219
+ googletest:: matchers:: __internal_unstable_do_not_depend_on_these:: compile_assert_and_match(
220
+ |actual| {
221
+ // Exhaustively check that all field names are specified.
222
+ match actual {
223
+ #struct_name ( #( #empty_fields) , * ) => ( ) ,
224
+ // The pattern below is unreachable if the type is a struct (as opposed to
225
+ // an enum). Since the macro can't know which it is, we always include it
226
+ // and just tell the compiler not to complain.
227
+ #[ allow( unreachable_patterns) ]
228
+ _ => { } ,
229
+ }
230
+ } ,
231
+ #matcher)
232
+ } )
233
+ }
207
234
}
208
235
209
236
////////////////////////////////////////////////////////////////////////////////
0 commit comments