2

In a Rust program, I have a use case where I want to print either a number, or a pipe-separated vector of numbers, thus this simple wrapper enum:

pub enum OneOrMore<T> { One(T), More(Vec<T>) } 

which works fine. But then I wanted to move the format logic into the OneOrMore type, so I tried:

impl<T: Show> Show for OneOrMore<T> { fn fmt(&self, f: &mut Formatter) -> Result { match self { One(x) => x.fmt(f), More(xs) => /* vec_join(xs, "|") or whatever */, } } } 

Since the impl is parameterized, it's expecting a One<T> but my code is describing a One<_>. Problem is I can't figure out where to put the type parameter inside the match arms. The syntax guide doesn't give an example of matching on parameterized types, fmt itself doesn't accept a type parameter, and all my blind guesses (One(x: T), One<T>(x), etc) aren't valid Rust. Any ideas where I should indicate the type of the match arms?

1 Answer 1

4

In the match expression, self is of type &OneOrMore<T>, but the arm patterns are of type OneOrMore<T>; i.e. you're matching on references, but the arms are not references.

You can change the patterns to references:

impl<T: Show> Show for OneOrMore<T> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match self { &One(ref x) => x.fmt(f), &More(ref xs) => /* ... */, } } } 

or you can avoid having to repeat & by dereferencing self instead:

impl<T: Show> Show for OneOrMore<T> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match *self { One(ref x) => x.fmt(f), More(ref xs) => /* ... */, } } } 

Note that in both cases, we need to add the ref keyword on the x and xs bindings to create references to the OneOrMore's interior. In other words, without ref, x and xs would be of type T; with ref, they are of type &T. Without ref, the compiler complains that we're trying to move a value out of the OneOrMore, which isn't allowed through a borrow.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I completely misinterpreted the compiler error this time.
Standard Rust style is match *foo { Bar => () } rather than match foo { &Bar => () }, incidentally, though that can’t remain true for cases where the expression being matched on is a tuple, like match (self, other) { (&Foo, &Foo) => () }.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.