rust

How do I wrap multiple generic error types around a custom Error enum in Rust


How do I wrap multiple generic error types around a custom Error enum in Rust. Its pretty straightforward, I just want this to work.

enum Error<SPIE, PINE> {
  SpiError(SPIE),
  PinError(PINE),
  // other custom errors
}
impl<SPIE,PINE> From<SPIE> for Error<SPIE,PINE> {
  fn from(value: SPIE) -> Self {
      Self::SpiError(value)
  }
}
impl<SPIE,PINE> From<PINE> for Error<SPIE,PINE> {
  fn from(value: PINE) -> Self {
      Self::PinError(value)
  }
}

Instead the compiler complains that:

conflicting implementations of trait `From<_>` for type `Error<_, _>`

which I understand, but perhaps I can distinguish the two types somehow...


Solution

  • This cannot work, because there is no way to constrain SPIE and PINE to be different types. If you try to convert a Foo into an Error<Foo, Foo>, which From implementation should it use?

    I'm not really sure there is a better approach than just constructing the enum variant directly. If your goal is to be able to use ? in a function then you can just precede that with a call to map_err like .map_err(Error::SpiError)? to wrap the error in the SpiError variant.

    Two points that might make this even more ergonomic:

    Combining both of these, the previous map_err incantation can be shortened to .map_err(Spi)?. It's not automatic, but it's not a whole lot of boilerplate either -- I use exactly this approach all the time.