Description
I have an error propagation question I just can't wrap my brain around. I'm trying to write
let iface =
std::env::var("TOKEN") // Result<String, VarError>
.and_then(|token| iface::Iface::new(&token)); // Result<iface::Iface, iface::Error>
```, basically trying to turn `Result<T, E>` into `Result<U, F>` in one go. The compiler diagnostic is kind of cryptic:
mismatched types
expected enum Result<_, VarError>
found enum Result<iface::Iface, iface::Error>
What can I do here to propagate mismatched error types (really `Result` types) around? I know could separate things out -
```rust
let token = std::env::var("TOKEN")?;
let iface = iface::Iface::new(&token)?;
but that doesn't really give me what I want. Constructing the Iface is common to some other pieces of code, and some of those operations are still meaningful even if I can't construct an Iface. So I'd like to defer unwrapping the Result until later when certain operations must fail (thus the ? operator is a no-go).
Update
I think
#[derive(Debug, thiserror::Error)]
enum ProgramError {
VarError(#[from] VarError),
IfaceError(#[from] IfaceError)
}
let iface =
std::env::var("TOKEN")
.map_err(Into::<ProgramError>::into)
.and_then(|token|
Iface::new(&token)
.map_err(Into::<ProgramError>::into)
);
is a better expression of what I'm trying to do (and it works!) it just feels very cumbersome. Is there a better way to consolidate nested errors?