Or you can use a boxed error iirc. Matching on the type of error after you do that isn't exactly great but it's doable if all you want to do is bubble the error up.
Places where that approach really sucks include web api routes (unless I haven't figured out a trick yet). For example, rocket defines Responder on Result so long as the ok and error variants both define it, but since a boxed error is erased it doesn't function correctly.
You can use the Error trait [1] from the stdlib, implement it for your error types and then just use the trait in your Result. That way you don't need the types to match and you can convert between then as needed while adding the previous errors to the chain.
It doesn’t require it. Instead it could just generate the same error handling boilerplate. But I think it would be a mistake versus general purpose (generic) sum types a la Rust.