locate-dwarf
locate-dwarf copied to clipboard
anyhow Errors make it difficult to use this crate
I'm trying to integrate locate-dwarf
into my own crate but the usage of anyhow
has made it difficult for me to make decisions based on the errors returned. For example, I want to take a different action if an io error occurred in locate_debug_symbols
versus if there is no debug pointer to be found.
I'd be willing to change this crate to use thiserror
if you are open to it?
Yes, would be better to return a Result<Option<PathBuf>>
as debug info not being available isn't a fatal error.
I'd be willing to change this crate to use
thiserror
if you are open to it?
I had originally used failure
, but thiserror
is absolutely more useful for library crates.
I had originally used failure, but thiserror is absolutely more useful for library crates.
That is actually a myth in most cases. The way thiserror
is usually abused people put all the possible errors that any code path in a crate could have in an enum and then return it from everywhere. The main argument for thiserror
is handling all possible errors and have the compiler check that all cases are handled. Which is a bad argument for one because not all errors are possible in every code path and the wrapping and rewrapping of errors (each library has at least an Io variant) actually makes it harder, and most ways of handling errors involve one of retrying/logging/aborting. And there are a whole host of other reasons why that "rule of thumb" brainlessly applied yields worse results than just using anyhow. You need to capture your backtraces manually which absolutely no one does, it's slower, etc.
And in this case the library is so trivial that an Option
is a much better solution anyway. However where thiserror
shines is in conveniently deriving Display
.
EDIT: sorry if it came of as a little aggressive, I just don't like "wisdom of the crowd" being justified by it's "the wisdom of the crowd". I'm happy to hear why thiserror is perfectly suited for this crate.
sorry if it came of as a little aggressive, I just don't like "wisdom of the crowd" being justified by it's "the wisdom of the crowd". I'm happy to hear why thiserror is perfectly suited for this crate.
No worries, I understand thiserror
makes it super easy for someone to just add in all possible errors. That's not what I'm suggesting. I just like thiserror
for two reasons (one of which you mentioned).
- It derives
Display
for you - It makes using
source
very easy (ok... this may be exactly proving your point, but in some cases it's very useful)
And in this case the library is so trivial that an Option is a much better solution anyway.
I started down this path but there are a couple errors that are explicitly handled in this crate. I believe they are ok to switch to Option
but would love feedback on that decision. Specifically they are:
- The given build-id to
locate_debug_build_id
is too short. - The parameter
path
passed intolocate_gnu_debuglink
can not becanonicalize
'd or does not have a parent. - The
object::Object
variable in locate debug symbols has some error when attempting to readmach_uuid
,build_id
, orgnu_debuglink
. - Rust can't convert the debuglink path to a real path.
For case 1, if the buildid is less than 2 bytes we should return None
because it wouldn't be in a .build-id folder anyway.
For case 2, we can return None
since a path that did not have a parent would not work for all those searches anyway.
For case 3, these will all occur if the passed in object
was corrupted in some way. It might be nice for the user to know that but we could also say " if that data is corrupted, we can't find the dwarf anyway
For case 4, if the path is invalid UTF-8, we won't be able to find the dwarf anyway.
I'd suggest returning an error if there is corruption or a transient error and None
if it isn't found. A transient error would be an io error that could just be ?
. For the corruption case it may be worth enumerating the cases like this:
#[derive(Debug, Error)]
pub enum CorruptObject {
#[error("build id is too short")]
BuildIdTooShort,
...
}
This way if someone really wants to handle the corrupt/transient errors differently they can use downcast_ref::<CorruptObject>
or downcast_ref::<std::io::Error>
and backtraces are still captured (as the return type would be an anyhow::Result
).
I've created a PR #49 that partially completes this work. It adds in the Option
to the success case of the returned path. But it does not include the custom error object. I'm working on that next.
FWIW, having just run into a similar issue attempting to use this crate for a small tool, I can say that at a bare minimum whatever error type this crate returns needs to be exported as part of the public API. At present it's not possible to refer to locate_dwarf::Error
.
A bit late, but in re:
I had originally used failure, but thiserror is absolutely more useful for library crates.
That is actually a myth in most cases
I simply meant "failure
is unmaintained, thiserror
is under active development".
To the original point of this issue: anyhow
seems intended for application usage, not library usage, for the "roll all errors up into a single error type" use case. I'm not particularly hung up on this.
Not really that bothered since I'm not currently using locate-dwarf. But you're not going to convince me that thiserror is better for library crates than anyhow for various reasons I mentioned. It may be that in some cases it's a better fit when done correctly. But if you're just wrapping every error from every dependency in a new enum it's not the case. And please make sure that at least the backtrace is captured and unwrapping an error actually displays were the error was constructed and not where it was unwrapped.