Skip to content

Commit 0f21a82

Browse files
marcianxcopybara-github
authored andcommitted
Make matches_pattern support _ at the top level in tuple structs.
This change is not backward-compatible since: * Some things that previously fell back to `match` pattern matching now use `match_pattern!`'s specialized matching, which requires the matched object to implement `Debug`. Toward #447 PiperOrigin-RevId: 700889703
1 parent 16e975d commit 0f21a82

File tree

2 files changed

+29
-29
lines changed

2 files changed

+29
-29
lines changed

googletest/tests/matches_pattern_test.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,18 @@ fn matches_tuple_struct_with_two_fields_and_trailing_comma() -> Result<()> {
439439
)
440440
}
441441

442+
#[test]
443+
fn matches_tuple_struct_with_interleaved_underscore() -> Result<()> {
444+
#[derive(Debug)]
445+
struct NonCopy;
446+
#[derive(Debug)]
447+
struct AStruct(u32, NonCopy, u32);
448+
let actual = AStruct(1, NonCopy, 3);
449+
450+
verify_that!(actual, matches_pattern!(&AStruct(eq(1), _, eq(3))))?;
451+
verify_that!(actual, matches_pattern!(AStruct(eq(&1), _, eq(&3))))
452+
}
453+
442454
#[test]
443455
fn matches_enum_without_field() -> Result<()> {
444456
#[derive(Debug)]
@@ -501,15 +513,6 @@ fn matches_match_pattern_struct() -> Result<()> {
501513
verify_that!(actual, matches_pattern!(AStruct { .. }))
502514
}
503515

504-
#[test]
505-
fn matches_match_pattern_tuple() -> Result<()> {
506-
#[allow(dead_code)]
507-
#[derive(Debug)]
508-
struct AStruct(u32);
509-
let actual = AStruct(123);
510-
verify_that!(actual, matches_pattern!(AStruct(_)))
511-
}
512-
513516
#[test]
514517
fn generates_correct_failure_output_when_enum_variant_without_field_is_not_matched() -> Result<()> {
515518
#[derive(Debug)]

googletest_macro/src/matches_pattern.rs

+17-20
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use syn::{
1818
parse::{Parse, ParseStream, Parser as _},
1919
parse_macro_input,
2020
punctuated::Punctuated,
21-
Expr, ExprCall, ExprInfer, Pat, Token,
21+
Expr, ExprCall, Pat, Token,
2222
};
2323

2424
/// This is an implementation detail of `googletest::matches_pattern!`. It
@@ -147,21 +147,15 @@ struct TupleFieldPattern {
147147
matcher: Expr,
148148
}
149149

150-
impl Parse for TupleFieldPattern {
150+
struct MaybeTupleFieldPattern(Option<TupleFieldPattern>);
151+
152+
impl Parse for MaybeTupleFieldPattern {
151153
fn parse(input: ParseStream) -> syn::Result<Self> {
152-
let ref_token = input.parse()?;
153-
let matcher = input.parse()?;
154-
match matcher {
155-
// `_` is an expr in const generics contexts, but is not supported in regular
156-
// `Expr` use like in the `matches_pattern` custom syntax. So fail in that case.
157-
// That should allow `into_match_expr` above to fall back to `into_match_pattern_expr`
158-
// and still attempt to parse `matcher` as a pattern.
159-
Expr::Infer(ExprInfer { underscore_token, .. }) => compile_err(
160-
underscore_token.spans[0],
161-
"unexpected `_` for `matches_pattern!` tuple field matcher",
162-
),
163-
_ => Ok(TupleFieldPattern { ref_token, matcher }),
164-
}
154+
let pattern = match input.parse::<Option<Token![_]>>()? {
155+
Some(_) => None,
156+
None => Some(TupleFieldPattern { ref_token: input.parse()?, matcher: input.parse()? }),
157+
};
158+
Ok(MaybeTupleFieldPattern(pattern))
165159
}
166160
}
167161

@@ -170,13 +164,16 @@ fn parse_tuple_pattern_args(
170164
struct_name: TokenStream,
171165
group_content: TokenStream,
172166
) -> syn::Result<TokenStream> {
173-
let parser = Punctuated::<TupleFieldPattern, Token![,]>::parse_terminated;
174-
let fields = parser.parse2(group_content)?.into_iter().enumerate().map(
175-
|(index, TupleFieldPattern { ref_token, matcher })| {
167+
let parser = Punctuated::<MaybeTupleFieldPattern, Token![,]>::parse_terminated;
168+
let fields = parser
169+
.parse2(group_content)?
170+
.into_iter()
171+
.enumerate()
172+
.filter_map(|(index, maybe_pattern)| maybe_pattern.0.map(|pattern| (index, pattern)))
173+
.map(|(index, TupleFieldPattern { ref_token, matcher })| {
176174
let index = syn::Index::from(index);
177175
quote! { googletest::matchers::field!(#struct_name.#index, #ref_token #matcher) }
178-
},
179-
);
176+
});
180177
Ok(quote! {
181178
googletest::matchers::__internal_unstable_do_not_depend_on_these::is(
182179
stringify!(#struct_name),

0 commit comments

Comments
 (0)