Reputation: 30845
I have the following code:
/// An error that encapsulates all possible configuration errors.
#[derive(Debug)]
pub enum Error {
/// An error that occured while parsing a yaml configuration.
Yaml(serde_yaml::Error),
}
impl From<serde_yaml::Error> for Error {
fn from(err: serde_yaml::Error) -> Error {
Error::Yaml(err)
}
}
/// A `Result` type alias for this config module's `Error` type.
pub type Result<T> = ::std::result::Result<T, Error>;
pub fn new(mut args: env::Args) -> Result<Config, Error> {
// initialize config_file variable
let config = serde_yaml::from_reader(config_file)?;
Ok(config)
}
serde_yaml::from_reader
returns a serde_yaml::Result
which uses serde_yaml::Error
for the Result
's error type. The code above compiles just fine.
That said, it seems a little funny that I should have to unwrap the Result
given back to me from calling serde_yaml::from_reader
only to then immediately repackage in into a new Ok
. In other words, I'd really like to be able to just write:
pub fn new(mut args: env::Args) -> Result<Config> {
// initialize config_file variable
serde_yaml::from_reader(config_file)
}
But when I try to do this, I get the following compiler error:
error[E0308]: mismatched types
--> src/config.rs:28:9
|
18 | pub fn new(mut args: env::Args) -> Result<Config> {
| -------------- expected `std::result::Result<config::Config, config::Error>` because of return type
...
28 | serde_yaml::from_reader(config_file)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `config::Error`, found struct `serde_yaml::Error`
|
= note: expected type `std::result::Result<config::Config, config::Error>`
found type `std::result::Result<_, serde_yaml::Error>`
What's going on here and what's the most idiomatic thing to do in this situation? Should I just leave my code as is?
Upvotes: 2
Views: 5202
Reputation: 59145
You have two different error types. Different types aren't compatible. There's nothing more to it than that.
It's worth noting that you're not just "re-wrapping" the value; you're pulling the initial Result
value apart, doing a conversion of the error type, branching out of the function if there was an error, then re-wrapping the value into a different Result
type. Also, you don't even need the variable there; you could equally write it as Ok(serde_yaml::from_reader(config_file)?)
.
If you really don't want to use ?
and Ok
, you can do the error conversion another way:
serde_yaml::from_reader(config_file)
.map_err(|e| e.into())
But that's essentially the same thing, sans the "early return on error" part.
Upvotes: 7