-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make adding paths to I/O errors even simpler #62
Comments
In my opinion, no. I don't think paths contain enough information on their own to construct a relevant error message. What would the error message in the second case be? We could follow the example of Imo, if you want a general solution for this where you don't have to think about adding the path, crates like But even beyond that, I don't personally like using crates like I understand that there's tension here. This approach makes it easy to forget to introduce wrapping errors that contextualize what you were doing and the relevant state, making it easy to lose path information like this. So in a sense I'm not confident that my approach is the best one, but if I had to choose an alternative I'd prefer something like |
Thank you for the detailed response!
Just a concatenation of the I/O error description with the path, with a joiner like fs::read(path).wrap_err_with(|| path.display().to_string())
My experience suggests this is a common case that deserves a special function. Cases where files are processed without an
I didn't know about this alternative; thanks for the pointer. To give an idea of my perspective (not that I expect you to share it): As a practitioner, I would like |
Aah, adding the info to the end of the existing error message without adding a new error to the chain of errors available via Regardless though, I think this is absolutely something that you could add as a helper trait locally, test out, and then report back how it went. It would look something like this: use std::io;
use std::path::PathBuf;
// replace this with the type you actually care about such as `eyre::Report` or `io::Error`
// or some custom wrapper type.
struct WrappedIoError;
trait WithPath {
type Return;
fn wrap_err_with_path(self, path: PathBuf) -> Self::Return;
}
impl WithPath for io::Error {
type Return = WrappedIoError;
fn wrap_err_with_path(self, _path: PathBuf) -> Self::Return {
todo!("append the pathbuf to the io::Error")
}
}
impl<T> WithPath for Result<T, io::Error> {
type Return = Result<T, <io::Error as WithPath>::Return>;
fn wrap_err_with_path(self, path: PathBuf) -> Self::Return {
self.map_err(|err| err.wrap_err_with_path(path))
}
}
I don't know your specific use cases so this may be entirely reasonable, but I don't generally view
I'm not following this bit, what do you mean by "Cases where files are processed without an io::Error"? The issue I was bringing up is that |
Chiming in to this. I have throughout a couple of points in my Rust journey encountered this same issue of "I need a file path with this". While providing a file path initially aids debugging, they do not as @yaahc put it contribute much more of what was attempted to be done. Did we fail to read a config file? An image for displaying the UI, the project file etc. Each of these are different in their own right, and as such deserve their own context. Adding the ability for Eyre to change the shape of the internal error message, rather than adding more causes in the chain. This not only creates a surprising side effect gotcha if the type matches, but also leads to Eyre being able to act in two different ways, without necessarily being clear which one will be used for a given case. I always tend to keep my apis predictable and strive towards making the api have one way, and one way only to achieve each distinct goal. What I've done in more recent times is read_config(path).await.wrap_err!(|| eyre!("Failed to read config file {path:?} specified by env"))? This makes it clear what failed and why it failed, but also how it got there |
Currently the docs suggest doing something like
This is such a common case that the above code just becomes boilerplate. It would be nicer if it were just
The text was updated successfully, but these errors were encountered: