Comments (11)
Wouldn't you then alternate your and_then
calls with .wrap_err("error message")?
calls?
There's already plenty ways to produce reports from other errors.
from eyre.
You cannot alternate, when and_then crashes. and_then is defined as pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E>
There is only one error type E
. When having a Result<_, Report>
and_then
only applies to functions returning an Result<_, Report>
. If you try to chain a like IoResult with IoError, you cannot do. You get:
note: expected enum Result<_, ErrReport>
found enum Result<std::string::String, std::io::Error>
And Option has option.ok_or_eyre()
from eyre.
Could you please post some working example code?
from eyre.
let cookie_file = Some("path"); // None
let cookie_jar = cookie_file
.ok_or_eyre("")
.and_then(File::open);
// more chained methods, later a single default for all error cases.
from eyre.
Why would you chain on the Result
, rather than propagate the error?
E.g.
use std::fs::File;
use eyre::OptionExt;
fn main() -> eyre::Result<()> {
let cookie_file = Some("path"); // None
let _cookie_jar = File::open(cookie_file.ok_or_eyre("must provide cookie file path")?)?;
Ok(())
}
If you require chaining because your simplified code is actually a stream or iterator combinator, then convert your custom Result::Err(_)
to Report
as usual within the closure:
use std::fs::File;
use eyre::{OptionExt, WrapErr};
fn main() -> eyre::Result<()> {
let cookie_file = Some("path"); // None
let _cookie_jar = cookie_file
.ok_or_eyre("must provide cookie file path")
.and_then(|path| File::open(path).wrap_err("failed to open cookie jar"))?;
Ok(())
}
However, I would strongly advise to propagate errors where they occur, rather than dragging them through long chains. The latter gets quite opaque quickly.
E.g. in the example, the error might be created at ok_or_eyre
, but is only propagated later at the ?
. This is not entirely obvious at first glance, and even less when code gets more complex.
In a real life application, I would always propagate immediately:
use std::{fs::File, path::Path};
use eyre::{OptionExt, WrapErr};
fn main() -> eyre::Result<()> {
// External arg, not known in advance.
let maybe_cookie_file_path = Some(Path::new("path")); // None
// We either bail or continue on the happy path, with `path: &Path`.
let path = maybe_cookie_file_path.ok_or_eyre("must provide cookie file path")?;
// Again, bail (propagating the error to the caller)
// or continue on the happy path with `cookie_jar: File`.
let cookie_jar = File::open(path).wrap_err("failed to open cookie jar")?;
// Do something with `cookie_jar`.
todo!();
Ok(())
}
from eyre.
In this case for any kind of error in this chain a (the same) default should apply.
.and_then(|path| File::open(path).wrap_err("failed to open cookie jar"))?;
The idea was to make this expression a little bit boilerplate-ly. If you prefer the explicit version, then we'd better close the issue.
from eyre.
I see what you mean. I think what your are really looking for is try
blocks. These are currently unstable.
You can read a succinct overview in the unstable book and follow the tracking issue.
This would allow you to bail using ?
in a chain and map/wrap the try block’s result err with eyre.
In stable rust, you could, as a workaround, refactor your combinator chain into a function returning plain Result<T, Box<dyn Error>>
and then use eyre on the function call’s return value.
Alternatively, following your initial design, you could implement the methods you proposed on a ResultExt
trait.
I can’t make the call for if such an extension trait should be part of eyre. However, you can safely assume that maintainers of this crate are going to have read your proposal and might chime in to the discussion with their own thoughts on the matter.
Also you might like to consider joining the eyre Discord for some closer contact. Please don’t feel discouraged, I might just misunderstand you, and my role on this team is very small. I’m in no position to accept or reject your proposal. I’ve just been trying to think along.
from eyre.
@Beiri22
you can try defining a trait like
trait AndThenEyre<T, E1> {
fn and_then_eyre<U, E2, F>(self, op: F) -> Result<U, eyre::Report>
where
F: FnOnce(T) -> Result<U, E2>;
}
impl<T, E1> AndThenEyre<T, E1> for Result<T, E1> {
fn and_then_eyre<U, E2, F>(self, op: F) -> Result<U, eyre::Report>
where
F: FnOnce(T) -> Result<U, E2>,
{
match self {
Ok(t) => match op(t) {
Ok(u) => Ok(u),
Err(e2) => Err(eyre::Report::from(e2)),
},
Err(e1) => Err(eyre::Report::from(e1)),
}
}
}
this may sound useful (I sure wish I had something like this), but there's a fundamental limitation here.
this would require you to add the bounds
E1: std::error::Error + Send + Sync + 'static
E2: std::error::Error + Send + Sync + 'static
...and the problem here is that eyre::Report
does not (and as I understand it, cannot) implement std::error::Error
. so:
- you can't call this on
eyre::Result
- you can't call this with any
op
that returnseyre::Result
- even if you call this on a
Result<T, E1>
with anop
that returnsResult<U, E2>
where bothE1
andE2
implementError
, you now have aneyre::Result
so you can never chain anotherand_then_eyre
so not only does this limit the usefulness of this function, it just makes this API weird in the context of a crate that wants to encourage you to use eyre::Report
.
from eyre.
Yes, its difficult to achive. In my case I used the functions of the original post put in an extention trait to result:
pub trait ResultExt<T> {
fn and_then_eyre<E: Error + Send + Sync + 'static, U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> std::result::Result<U, Report>;
fn and_then_dyn_eyre<E: Error + Send + Sync + ?Sized + 'static, U, F: FnOnce(T) -> Result<U, Box<E>>>(self, op: F) -> std::result::Result<U, Report>;
}
to make it work for my specific case.
from eyre.
@Beiri22 Are you okay with having this issue closed?
from eyre.
sure
from eyre.
Related Issues (20)
- Extend `Option` with `ok_or_eyre`? HOT 2
- Improve discoverability of `OptionExt::ok_or_eyre` HOT 2
- Ergonomics: Hide `context` behind a feature HOT 4
- [breaking] remove alias exports `DefaultContext` and `EyreContext`
- [breaking] Remove `anyhow` from default features HOT 2
- `cargo doc` warning: "this URL is not a hyperlink"
- Segfault in `Report::downcast()` introduced in 0.6.9 HOT 6
- enable raw mode compatibility for panic & error reports HOT 1
- `fn Ok()` breaks all code with `use eyre::*` in new releases HOT 5
- `OptionExt` feature test is incorrectly feature-gated behind the `anyhow` flag
- [ BREAKING ] `ContextCompat` contains identically named methods to `WrapErr` which can be confusing and a footgun HOT 1
- [email protected] missing in the repository? HOT 2
- Eyre broken in rust-analyzer with nightly HOT 1
- docs: enclosing in backticks HOT 1
- Implement From for anyhow errors
- New version of backtrace doesn't export `gimli-symbolize` anymore
- Path to 1.0
- DISCUSS: merge eyre and anyhow libraries HOT 1
- Add pre-hook callbacks HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from eyre.