3 releases
0.1.2 | Sep 12, 2021 |
---|---|
0.1.1 | Jul 18, 2020 |
0.1.0 | Sep 24, 2019 |
#447 in Command-line interface
3,748 downloads per month
Used in 27 crates
(23 directly)
9KB
main_error
Print errors with Display
instead of Debug
when using ?
in main()
. For example:
use main_error::MainError;
fn main() -> Result<(), MainError> {
// This prints
// "Error: invalid digit found in string"
// instead of (if you used `Result<(), Box<dyn Error>>` or similar)
// "ParseIntError { kind: InvalidDigit }".
let number: i32 = "not a number".parse()?;
Ok(())
}
For more info, see:
- Package information on crates.io
- Documentation on Docs.rs
- Usage examples in the repo
lib.rs
:
Print errors with Display
instead of Debug
when using ?
in main()
.
Use by returning MainError
as the error type from main()
.
Example:
use main_error::MainError;
fn main() -> Result<(), MainError> {
// This prints
// "Error: invalid digit found in string"
// instead of (if you used `Result<(), Box<dyn Error>>` or similar)
// "ParseIntError { kind: InvalidDigit }".
let number: i32 = "not a number".parse()?;
Ok(())
}
For convenience, you can also use the MainResult
type.
See below for more details.
The Issue
Since Rust 1.26, main()
function can return a Result<T, E>
.
This enables the use of ?
for convenient error handling in small programs and quick examples (RFC).
Unfortunately, the error is printed via Debug
(hardcoded in the standard library, search for "Error:"),
which gives not very pretty or human-friendly output.
For example, this program:
fn main() -> Result<(), ParseIntError> {
let num: i32 = "not a number".parse()?;
// ...
}
will print
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
use main_error::MainError;
fn main() -> Result<(), MainError> {
let _: i32 = "not a number".parse()?;
// ...
}
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. Reasons:- It's not necessary, because the standard library only requires
E: Debug
formain() -> Result<T, E>
. - You should only be using
MainError
formain()
anyway, whereas theError
trait is more for interoparability between libraries. - One simply cannot implement
Error
forMainError
, because this would create an overlappingimpl
.
Explanation:MainError
can be converted from aT: Into<Box<dyn Error>>
.Into<Box<dyn Error>>
is implemented forE: Error
itself.- If
MainError
would implementError
, it could be converted from itself. - This collides with the reflexive
impl<T> From<T> for T
in core.
- It's not necessary, 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.