I have two functions that are similar but can fail with different errors:
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("error a")]
MyErrorA,
#[error("error b")]
MyErrorB,
#[error("bad value ({0})")]
MyErrorCommon(String),
}
fn functionA() -> Result<String, MyError> {
// can fail with MyErrorA MyErrorCommon
todo!()
}
fn functionB() -> Result<String, MyError> {
// can fail with MyErrorB MyErrorCommon
todo!()
}
Is there an elegant (*) way I can express this?
If I split the error type into two separate types, is there a way to reuse the definition of MyErrorCommon?
(*) by “elegant” I mean something that improves the code - I’m sure one could define a few macros and solve that way, but I don’t want to go there
edit: grammar (rust grammar)
You can’t create a subset of an enum directly, but splitting this up into multiple types works. You can have
FunctionAErrorwith errors that function can produce and a variant for your common errors, andFunctionBErrorwhich is similar:#[derive(Debug, Error)] enum MyErrorCommon { #[error("bad value ({0})")] MyErrorCommon(String), } #[derive(Debug, Error)] enum FunctionAError { #[error("error a")] MyErrorA, Common(#[from] MyErrorCommon), } // and same for FunctionBErrorThe try operator (
?) will automatically useFromimpls to convert errors for you as well. If a function returns a result containingMyErrorCommonin your function and you use?on it, it gets converted to that function’s error type for you.thiserrorgenerates theFromimpl for you if you use#[from].use-case?
Different functions whose possible failure reasons have a non-empty intersection, but don’t coincide completely (IDK if this clarifies? I think the example code in the OP is clearer)
Yeah, I got that.
I’m asking what would be the benefit of not using a single error enum for all failure reasons?


