-
Notifications
You must be signed in to change notification settings - Fork 111
[WIP] Add derive block for deriving additional traits on error types #163
base: master
Are you sure you want to change the base?
[WIP] Add derive block for deriving additional traits on error types #163
Conversation
I like this! Could you also update the changelog and add some tests? |
I got the trait generation working, and added a generic parameter to trait Trait: Foo + Bar {} The #[derive(Foo, Bar)] And instead of storing There are two things left to do:
@Yamakaky Perhaps you can help with the first problem? I'm trying to make an example of what the expansion should look like (maybe it will help find the solution): // Example usage:
error_chain! {
derive {
PartialEq
}
}
// Should expand to this (ignoring irrelevant generated code):
trait Trait: PartialEq {}
impl<T: PartialEq> Trait for T {}
#[derive(PartialEq)]
struct Error(ErrorKind, State<Trait>);
// How I imagine code would use this:
assert_eq!(error, "error!".into()); Deriving |
src/error_chain.rs
Outdated
links $b | ||
foreign_links $c | ||
errors $d | ||
derive $b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you name id $e
instead of shuffling everything?
src/error_chain.rs
Outdated
@@ -54,6 +58,10 @@ macro_rules! error_chain_processed { | |||
} | |||
|
|||
) => { | |||
use ::std::fmt::Debug; | |||
use ::std::error::Error as StdError; | |||
create_super_trait!(Trait: Debug, StdError, Send $(, $bound)*); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will not work if you define multiple errors in the same module.
Also, can you remove use
and use absolute path instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a limitation of the create_super_trait
macro currently. I will work on getting it fixed.
|
I fixed the macro, and reverted the shuffling of things. I originally shuffled them to allow overrideable defaults for the Everything should be functional now, but deriving I think comparing the entire chain would be useful to some, as a test may want to assert that the correct error chain is generated, not just the top level error. However, if someone wanted this, they could just iterate through the error chain and test each individual error. |
I think the best way forward is to separate the derive name from the bound name, so the macro would be used like this: error_chain! {
derive {
// Format is `Trait, Bound`, separated by semi-colons
PartialEq, PartialEq<Error>; Serialize, serde::Serialize
}
} This allows users to derive If users don't derive anything, there is still an error here, stating that it expected Also, |
Any updates on this? This is something I sorely need. |
I ran into some problems when implementing this, I can take a look at it soon to see if I can fix it. |
2d30426
to
1a67b33
Compare
This is really complicated - good luck with it! |
Unfortunately I got stuck again while implementing this. @samnardoni Can you provide an example of how you would use this feature? If a general solution isn't possible, it may be best to provide special cases for commonly used derives like |
@pengowen123 Sorry about taking so long to reply. I can't remember exactly which derive I wanted, but from thinking back to what I was working on, I'm 90% sure it was I don't really have any examples of how I'd want to use it in particular; all I know is I really wanted my error type to be serializable so I could send it over a little RPC service I wrote with the |
Still conflicting ^^ |
Re-order the derive block internally
Add temporary #![feature(log_syntax)]
30683a6
to
f190643
Compare
I renamed impl PartialEq for Error {
fn eq(&self, other: &Error) -> bool {
let state = self.state.inner == other.state.inner;
let kind = self.kind == other.kind;
state && kind
}
} The main problem now is the |
Sad that this seems to have died of inattention. |
Fixes #134.
Syntax is same as the
types
block:The only difference is there is no semicolon at the end of the list of traits (it is complicated to add, and I just wanted to get the macro working first). The new feature seems to work fine, now the only thing left to do is to make it useful. I ran into the problems listed in this comment, and I'm not sure how to implement the suggested solution.
The suggested solution is to generate a trait with
Self
bound by the requested traits, and implement the trait for all types that implement the traits it is bound by. Using the above example, this trait would look like this:The
Debug
,Error
, andSend
bounds are always required so they are inserted for all generated traits. However, I don't know how to generateHash + Eq + PartialEq
with a macro because$($trait)+*
won't work. I will try to make this work, I just wanted some initial feedback. When this is all complete, I can change the block to be a more generalattributes
block as requested in this comment