-
-
Notifications
You must be signed in to change notification settings - Fork 160
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
Generate From impls #2
Comments
For the case of lots of variants that all want a #[derive(Error, Debug)]
#[error(from_source)]
pub enum E {
E0(#[source] io::Error),
E1(#[source] serde_json::Error),
E2(#[source] regex::Error),
E3(#[source] hyper::Error),
E4(#[source] anyhow::Error),
} |
I've been poking at this a little; for structs, should this only work if there's one field (which is |
The behavior of the attributes (AFAICT) is that "first found wins", so the first found with the attribute or with the right name would be found as the |
"First found wins" is not intended behavior, I filed #6 to fix it. The |
Thanks for the clarification @dtolnay. I know there's some issues to triage, but I do plan to try my hand at implementing some of these fixes anyhow to learn more about macros, so let me know if I can be of help. @mathstuf my question above was not directed as much at knowing which field to to use; but rather about how in the |
Oh, that's a good point. Maybe |
Just a note that there may be multiple enum variants with the same
Or, the derive could just report an error and ask the user to manually impl It looks like It seems like you're trying to keep |
+1, it should produce a targeted error underneath one of the pair of overlapping source types.
I would lean toward erroring out. I don't want any no_from attribute for now. |
@dtolnay, two questions:
|
|
If we want |
I'm the author of derive_more. I saw this crate popping up on reddit and I like the way this crate derives the Error trait. Then I saw this issue and I was thinking that another solution would be to combine forces on this. The current master branch of derive_more supports the following // Default not from
#[derive(From, Debug)]
enum EnumError {
#[from]
Example(io::Error),
NotFromable(i32),
}
// Default from
#[derive(From, Debug)]
enum EnumError {
Example(io::Error),
#[from(ignore)]
NotFromable(i32),
} and together with the #[derive(From, Display)]
#[display(fmt="E prefix: {}")
pub enum E {
#[display(fmt='io error')]
E0(io::Error),
E1(serde_json::Error),
E2(regex::Error),
E3(hyper::Error),
E4(anyhow::Error),
#[from(ignore)]
#[display(fmt="wrong count {}", count)]
SomeCustomError{count: i32},
} I think it would be very nice if we could combine the good parts of this library and #[derive(From, Display, Error)]
#[display("E prefix: {}")
pub enum E {
#[display('io error')]
E0(io::Error),
E1(serde_json::Error),
E2(regex::Error),
E3(hyper::Error),
E4(anyhow::Error),
#[from(ignore)]
#[source(ignore)] // maybe #[error(ignore)]
#[display("wrong count {count}")]
SomeCustomError{count: i32, backtrace: Backtrace},
} @dtolnay what do you think? |
@JelteF that does not sound promising to me because error objects require a pretty error-specific impl of From when it comes to dealing with backtraces. |
I'm not entirely sure what you mean, wouldn't you want to simply forward the backtrace call to the source error? |
The From impl needs to capture a backtrace if the source error doesn't already have one. |
That's definitely a good point. Some options I can think of: // Specific solution for error, that does auto detection of backtrace field
#[derive(From, Debug)]
enum EnumError {
#[from(error)]
Example{error: io::Error, backtrace: Backtrace),
NotFromable(i32),
} // More general, but more verbose
#[derive(From, Debug)]
enum EnumError {
Example{
error: io::Error,
#[from(default="Backtrace::capture()")]
backtrace: Backtrace,
},
NotFromable(i32),
} Because of the way I've implemented attribute handling, the first one would also work easily for the big struct by putting the from attribute on the enum: #[derive(From, Display, Error)]
#[display("E prefix: {}")
#[from(error)]
pub enum E {
#[display('io error')]
E0{source: io::Error, backtrace: Backtrace},
E1{source: serde_json::Error, backtrace: Backtrace},
E2{source: regex::Error, backtrace: Backtrace},
E3{source: hyper::Error, backtrace: Backtrace},
E4{source: anyhow::Error, backtrace: Backtrace},
#[from(ignore)]
#[source(ignore)] // maybe #[error(ignore)]
#[display("wrong count {count}")]
SomeCustomError{count: i32, backtrace: Backtrace},
} I'll think a bit more about this, but I actually like the option above quite a bit. |
FYI to the people with 👍 reaction above -- @drrlvn @Alexendoo @hwchen @joseluis @CAD97 @NAlexPear @jplatte @mitchmindtree @twistedfall @Jezza @MikailBag @MOZGIII
|
Currently fails with: error[E0034]: multiple applicable items in scope --> tests/test_backtrace.rs:165:13 | 165 | x: std::io::Error, | ^ multiple `provide` found | = note: candidate #1 is defined in an impl of the trait `Provider` for the type `E` = note: candidate #2 is defined in an impl of the trait `std::error::Error` for the type `std::io::Error` help: disambiguate the associated function for candidate #1 | 165 | Provider::provide(&x, Error): std::io::Error, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help: disambiguate the associated function for candidate #2 | 165 | std::error::Error::provide(&x, Error): std::io::Error, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error types commonly provide
From
impls so that they can be constructed by?
.I don't want to become a fully general
From
derive, but I would be okay with providing a convenientFrom
impl just for sources. AnyFrom
impl other than from the source should be handwritten for visibility or using something like derive_more.The text was updated successfully, but these errors were encountered: