Pattern syntax for Vec<T> in respect to assert_matches!()

I create the following custom container type S and some inner type T.

struct T(u32);
struct S(Vec<T>);

impl std::str::FromStr for S {...}

I can't just

type S = Vec<T>;

because impl FromStr for S errors:
error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate

This is fine.

Now I'm writing some tests to validate from_str() behaviour.
Using Tracking Issue for assert_matches · Issue #82775 · rust-lang/rust · GitHub to get nice error messages on test failures I write the following

    let s = "1 2 3";
    let parsed = s.parse::<S>();
    assert_matches!(parsed, Ok(S([T(1), T(2), T(3)])));

Aside from whether it makes sense; it's intuitive for me to write it like this.
Unfortunately this doesn't work

error[E0529]: expected an array or slice, found `Vec<T>`
  --> src/main.rs:20:34
   |
20 |     assert_matches!(parsed, Ok(S([T(1), T(2), T(3)])));
   |                                  ^^^^^^^^^^^^^^^^^^ pattern cannot match with input type `Vec<T>`
   |
help: consider using `as_deref` here
   |
20 |     assert_matches!(parsed.as_deref(), Ok(S([T(1), T(2), T(3)])));
   |                           +++++++++++

For more information about this error, try `rustc --explain E0529`.

When I used the compiler hint above, it didn't resolve the issue.
I can however do this:

    assert_matches!(parsed, Ok(S(..)));
    let s_inner = parsed.unwrap().0;
    assert_matches!(s_inner.as_slice(), [T(1), T(2), T(3)]);

So my questions here are:

  • How should I've written the code to be idiomatic in the scenario above?
  • How should the compiler hint above be changed?

I believe this thread could be considered continuation of

Yup. In particular, it is a consequence of this observation. You can't destructure a Vec using pattern matching - you have to either use regular tools like boolean comparisons, or pattern match on it as a slice.

Personally, I'd do the former. matches! supports match predicates, so you can even combine them:

let parsed = parsed.expect("some explanation for why parsing always returns Ok");
assert_matches!(parsed, S(elements) if elements == vec![T(1), T(2), T(3)]);

Untested.

We may get deref patterns eventually, but it wouldn't apply to this (doubly) nested scenario.

Perhaps

    assert_matches!(parsed.as_ref().map(|s| &s.0[..]), Ok([T(1), T(2), T(3)]));
1 Like

We may get deref patterns eventually, but it wouldn't apply to this (doubly) nested scenario.

Do you think it would be worthwhile for me to open an issue at rust-lang/rust to discuss clarifying the compiler error and hint for matching against Vec?

Something like:
"You can't use array/slice pattern matching for Vec<T> because it behaves like a struct.
hint: First convert Vec<T> to a slice &[T]"

In general I think it's worth reporting cases like the original example which provide an incorrect suggestion.

Here's a pre-existing issue where you could add your example.