1

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...


Based on the accepted answer, ended up using this:

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

and mapping the errors like so: ce.set_low().map_err(Pin)?;

0

1 Answer 1

2

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:

  • The name SpiError is redundant when you're already in a type with an Error suffix -- why not enum Error<SPIE, PINE> { Spi(SPIE), Pin(PINE) }?
  • You can use Error::*; to import the variants directly.

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.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.