Reputation: 23
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?
Upvotes: 2
Views: 1410
Reputation: 65782
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.
Upvotes: 4