Box<dyn Error>
is handy for types that implement it:
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
Err("March")?
}
but surprisingly, it doesn't work with all types:
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// the trait `std::error::Error` is not implemented for `{integer}`
Err(9)?
}
as a workaround, you can use what I call the Error Format idiom:
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
Err(format!("{}", 9))?
}
Note this has many variations, for example with literals you can do this:
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
Err(concat!(9))?
}
and also, you may not even need to use Box<dyn Error>
:
fn main() -> Result<(), String> {
Err(concat!(9))?
}
It can also be useful in cases where you normally don't need it. For example, this example below could work without it, but it's useful as it adds the filename to the error, which normally isn't shown:
use std::fs;
fn main() -> Result<(), String> {
let s = "a.rs";
match fs::read_to_string(s) {
Ok(v) => print!("{}", v),
// normal message is just: The system cannot find the file specified
Err(v) => Err(format!("{} {}", s, v))?
}
Ok(())
}