|
|
|
|
|
by charliesome
2260 days ago
|
|
As the kind of more conservative Rust user GP references, I've had a great time with the derive_more crate's From derive [0]. This lets me write code like this: #[derive(From, Debug)]
pub enum SomeSpecificError {
Io(io::Error),
SomeAppLevelErrorCondition,
}
fn do_something() -> Result<(), SomeSpecificError> {
do_some_io()?;
// ...
}
Previously I would have written: fn do_something() -> Result<(), SomeSpecificError> {
do_some_io().map_err(SomeSpecificError::Io)?;
}
I find this approach results in clear code that continues to compile and work just fine over time, even as everything changes around it.[0] https://jeltef.github.io/derive_more/derive_more/from.html#e... |
|
In general, I feel `?`'s automatic `From::from` conversion leads to bad errors, because the programmer is incentivized to have type-specific context via implementing `From<>` rather than operation-specific context, even though operation-specific context leads to better error messages. Consider the difference between:
and Edit: I should add that it is possible to use `From<>` when the type-specific contexts and operation-specific contexts form a bijection. In the above example, if there were dedicated `struct ReadConfigError(std::path::PathBuf, std::io::Error)` and `struct ConnectToServerError(std::net::SocketAddr, std::io::Error)` types, then having the higher-level `Error` impl `From<ReadConfigError>` and `From<ConnectToServerError>` would be perfectly fine. Of course, that would just shift the issue down to those types since they would not be able to impl `From<std::io::Error>`. Also, in my experience, libraries rarely bother having such individual operation-specific error types anyway.