[−][src]Crate main_error
Print errors with Display
instead of Debug
when using ?
in main()
.
TL;DR
Use like:
ⓘThis example panics
use main_error::MainError; fn main() -> Result<(), MainError> { Err("string or a custom error type")? // prints using Display, not Debug }Run
See below for more details.
Problem
Since Rust 1.26, main
can return a Result<T, E>
.
This enables the use of ?
for convenient error handling (RFC). For example:
ⓘThis example panics
fn main() -> Result<(), ParseIntError> { let num: i32 = "not a number".parse()?; // will fail and print an error // ... }Run
Unfortunately, the error is printed via Debug
(hardcoded in the standard library), which gives not very pretty or human-friendly output.
For example, the error above is printed as:
Error: ParseIntError { kind: InvalidDigit }
Solution
This crate provides MainError
as a drop-in replacement for the error type E
in your main
's Result<T, E>
.
It prints the error via Display
instead of Debug
, which yields a nicer error message.
For example, the program above can be changed to
ⓘThis example panics
use main_error::MainError; fn main() -> Result<(), MainError> { let _: i32 = "not a number".parse()?; // ... }Run
and now prints:
Error: invalid digit found in string
Details and Drawbacks
MainError
stores the original error asBox<dyn Error>
. This incurs one allocation (on conversion) and one virtual call (on printing). Since there can be exactly one error like this before the program ends, this cost is insignificant.MainError
implementsFrom
for all types that can be converted into aBox<dyn Error>
.- This allows it to be used in place of any type that implements the
Error
trait (see example above). - It can also be used in place of any type that can be converted to a
Box<dyn Error>
, e.g.,String
.
- This allows it to be used in place of any type that implements the
MainError
does not implement theError
trait itself.- It doesn't have to, because the standard library only requires
E: Debug
formain() -> Result<T, E>
. - It doesn't need to, because the
Error
trait is mostly for interoperability between libraries, whereasMainError
should only be used inmain
. - It simply cannot, because this would create an overlapping
impl
.MainError
can be converted fromInto<Box<dyn Error>>
.Into<Box<dyn Error>>
is implemented forE: Error
itself. IfMainError
impl'sError
, it would meanMainError
could be converted from itself. This collides with the reflexiveimpl<T> From<T> for T
in core.
- It doesn't have to, because the standard library only requires
MainError
implementsDebug
in terms ofDisplay
of the underlying error. This is hacky, but unfortunatelyDebug
as the output for themain
error case is stable now. The"Error: "
part at the beginning of the output comes from the standard library, thus it cannot be changed.
Structs
MainError | Newtype wrapper around a boxed |