-
Notifications
You must be signed in to change notification settings - Fork 60
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
Any easy way to add common implicit data to an error enum? #468
Comments
Those would be the two approaches that I know of as well. Perhaps there could be a way to automatically fill in #[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum MyErrorEnum {
Err1 {
#[snafu(implicit)]
backtrace: Backtrace,
#[snafu(implicit)]
loc: Location,
#[snafu(implicit)]
span: Span,
},
// has a source with the backtrace
Err2 {
#[snafu(backtrace)]
source: BarError,
#[snafu(implicit)]
loc: Location,
#[snafu(implicit)]
span: Span,
},
// ...
} |
I appreciate this question because it's in the small set of things I can answer definitely: no. SNAFU is currently implemented as a derive macro and derive macros cannot modify the type they are attached to, they may only output additional code. It's actually on my long-term roadmap to rewrite to an attribute macro 1 because SNAFU produces additional types (the context selectors) and people generally don't expect a derive macro to do anything beyond implement a trait. Even in that future world, I don't know how I'd feel about SNAFU modifying the fields of the type. Perhaps some crate out there provides an attribute macro that will automatically add an attribute + field pair to every enum? If so, then you could use it in addition to SNAFU. In your case, it appears you have multiple implicit fields, so you could create a composite type that implements Another possibility is to have a wrapping error that contains the implicit data and then always convert the inner error to the wrapping error: use snafu::prelude::*;
#[derive(Debug, Snafu)]
enum Inner {
#[snafu(display("Bad thing 1"))]
Alfa,
#[snafu(display("Bad thing 2"))]
Beta,
}
#[derive(Debug, Snafu)]
#[snafu(transparent)]
struct Outer {
source: Inner,
#[snafu(implicit)]
location: snafu::Location,
}
fn inner_main(value: bool) -> Result<(), Outer> {
if value {
AlfaSnafu.fail()?;
} else {
BetaSnafu.fail()?;
}
Ok(())
}
#[snafu::report]
fn main() -> Result<(), Outer> {
let v = inner_main(std::env::args().count() > 1);
if let Err(e) = &v {
eprintln!("It happened at {}", e.location);
}
v
} This will run into some ergonomic problems around type inference sometimes though, so I wouldn't recommend it as a first solution.
Note that you don't need
It seems odd to have both of these as the backtrace should contain the location, no? Footnotes
|
yep, maybe attribute macro is more flexible. I use the second way to wrap the common implict data, but I write a lot of other convert function manaually, it's a littele bit weird, how I wish they were automatically generated😁 |
https://github.com/yuanyan3060/enum_expand Maybe you can try this crate, and if it works, I'll upload it to crate.io |
currntly, if i want to get a err enum with some same detail info ,i must define them in every enum variants.
or like this
Is there an easier way to do this without having to write frustratingly repetitive property values?
The text was updated successfully, but these errors were encountered: