Reputation: 48278
When writing code that uses Result
type, you may want different behavior for users and developers.
Result
.Err
value is created.If you make a unique error it's not hard to search for it, but if the error is from the standard library, the error may be very generic.
For example, it's impossible to know which read
command caused an unexpected end-of-file without manually changing every file.read()?
to file.read().unwrap()
.
Is there a convenient way to get a stack-trace from a Result
?
A weak but workable solution could be to make a macro for reading, read_in_release_unwrap_in_debug!(file, data)
... but this feels very awkward.
I have a file reader with many read
calls and one fails. I'm not sure which. At run-time, I want to push the result back to the caller. For debugging, I want the failed read call to stop or somehow let me know its line number.
Upvotes: 62
Views: 25934
Reputation: 97138
If you use anyhow
you can get this for free! You enable an environment variable:
RUST_BACKTRACE=1 cargo +nightly run
Also enable the backtrace
crate feature.
Upvotes: 23
Reputation: 14061
A result by itself doesn't have any backtrace information, but you can add it to custom error types.
The error_chain crate (which is unfortunately no longer maintained) is an example which generates an error type for you, for which you get backtrace generation for free when the RUST_BACKTRACE
environment variable is set.
You could also use the backtrace library directly and do it yourself.
Upvotes: 8
Reputation: 550
I resolve this requirement with easy-error crate, while error-chain crate is fine also.
Use Result defined in easy-error
as return type, then use context method to convert other Result
types.
Most important thing is to pass information to context
method with line number.
use easy_error::{Result, ResultExt};
use std::path::PathBuf;
fn test_open() -> Result<()> {
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
p.push("resources/test/songs.json");
File::open(p).context(format!("{}:{}", file!(), line!()))?;
Ok(())
}
To avoid typing format!("{}:{}", file!(), line!())
all the time, define a macro:
#[macro_export]
macro_rules! code_loc {
() => {
format!("{}:{}", file!(), line!())
};
}
And finally code will be:
File::open(p).context(code_loc!())?;
Upvotes: 4