bees
bees

Reputation: 23

Matching parameterized types in Rust

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

Answers (1)

Francis Gagn&#233;
Francis Gagn&#233;

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

Related Questions