Add PartialEq/Eq to errors for easier comparison#768
Add PartialEq/Eq to errors for easier comparison#768spacebear21 merged 1 commit intopayjoin:masterfrom
Conversation
60d5658 to
605fdfd
Compare
Pull Request Test Coverage Report for Build 16426338362Details
💛 - Coveralls |
605fdfd to
6ba5c92
Compare
DanGould
left a comment
There was a problem hiding this comment.
Thank you for giving this issue significant attention @w3irdrobot. This work is definitely on the path to more stable, usable public error API. However I do request some changes.
I used false in those implementations when the wrapped error did not implement these traits
It seems to me that the way to test error matching in cases where inner errors are not themselves PartialEq is to use match on the variants. In those cases implementing PartialEq for these types is simply not possible because getting a completely correct equality without having [Partial]Eq implemented on the underlying types is impossible. I think the best we can do is to keep PartialEq implementations only where all of the underlying errors are also PartialEq.
The biggest change here is the change of payjoin::ImplementationError from a type alias to a newtype
This seems to be an independent change from PartialEq/Eq implementation that merits its own commit, and perhaps its own PR, since it is distinct from the Eq implementation as far as I can tell. I welcome this change. It fixes a number of problems, including our inability to impl functions on the alias and the difficulty to generate FFI bindings.
To prevent adding a bunch of dependencies to payjoin, I also opted for manually wrapping errors using .map_err(ImplementationError::new) in many places instead of implementing From for ImplementationError.
I agree that this is the appropriate course of action. In fact, I would rather not even introduce anyhow to the core payjoin crate, nor implement the other From conversions for ImplementationError. I think we're better off doing manual maps where the interface requires an ImplementationError to be returned to explicitly mark those conversions.
It may well be that I wrote #645 before I understood that using match and matches! (or assert_matches! in newer versions of rust) to test error variants without PartialEq implementations would be the most appropriate, and that some variants are simply ineligible for PartialEq implementation. Your efforts here have furthered our collective knowledge about these mechanics and are not in vain.
| #[derive(Debug)] | ||
| pub struct ImplementationError(Box<dyn error::Error + Send + Sync>); | ||
|
|
||
| impl ImplementationError { | ||
| pub fn new(e: impl error::Error + Send + Sync + 'static) -> Self { | ||
| ImplementationError(Box::new(e)) | ||
| } | ||
| } |
There was a problem hiding this comment.
While I do believe such an ImplementationError is appropriate, I'm doubt that all of the From implementations, which are all part of the public API are when the simple Implementation::new type can be used.
payjoin/src/ohttp.rs
Outdated
| impl PartialEq for DirectoryResponseError { | ||
| fn eq(&self, other: &Self) -> bool { | ||
| match (self, other) { | ||
| (DirectoryResponseError::InvalidSize(s1), DirectoryResponseError::InvalidSize(s2)) => | ||
| s1 == s2, | ||
| ( | ||
| DirectoryResponseError::OhttpDecapsulation(_), | ||
| DirectoryResponseError::OhttpDecapsulation(_), | ||
| ) => true, | ||
| ( | ||
| DirectoryResponseError::UnexpectedStatusCode(s1), | ||
| DirectoryResponseError::UnexpectedStatusCode(s2), | ||
| ) => s1 == s2, | ||
| _ => false, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Eq for DirectoryResponseError {} |
There was a problem hiding this comment.
It seems to me that the way to test error matching in cases where inner errors are not themselves PartialEq is to use match, and implementing PartialEq for these types is simply not possible because getting a completely correct implementation is not available without being able to compare the underlying types.
There was a problem hiding this comment.
OK. So I should remove the manual implementations of PartialEq/Eq from the error types that can't just derive it?
|
@DanGould I've updated this PR to remove the manual equality trait implementations. I also removed most of the |
05b0c07 to
6363121
Compare
|
@w3irdrobot Thanks for updating this. May you please rebase your changes on master so that we can avoid a merge commit? |
21103cf to
8992982
Compare
|
@DanGould done. 💪 |
8992982 to
5fb2184
Compare
DanGould
left a comment
There was a problem hiding this comment.
I think this is ok, but most of the actual +/- changes in this PR are formatting changes which makes me uncertain whether or not I've checked all of the semantic changes. May those be removed so that this PR is limited to the actual PartialEq/Eq-related changes?
payjoin-cli/src/app/v2/mod.rs
Outdated
| ReceiveSession::Initialized(proposal) => { | ||
| self.read_from_directory(proposal, persister).await | ||
| } |
There was a problem hiding this comment.
It seems there are quite a few of these formatting changes that are unrelated to the semantic changes this PR wants to address. Would it be possible to remove them from the commit @w3irdrobot
There was a problem hiding this comment.
I can remove them but they were just made by running cargo fmt. I didn't manually make them.
There was a problem hiding this comment.
This happens when using the stable rust toolchain, you can either change your default to nightly with rustup default nightly or specify per command with cargo +nightly fmt (see https://github.com/payjoin/rust-payjoin/blob/master/.github/CONTRIBUTING.md#commits)
There was a problem hiding this comment.
i'm pretty sure i ran it with nightly but there's a chance i didn't.
There was a problem hiding this comment.
looks like that was the issue. ran it with nightly and it put things back. should be good now.
| target/aarch64-apple-darwin/release-smaller/$LIBNAME \ | ||
| target/x86_64-apple-darwin/release-smaller/$LIBNAME | ||
| target/aarch64-apple-darwin/release-smaller/$LIBNAME \ | ||
| target/x86_64-apple-darwin/release-smaller/$LIBNAME |
There was a problem hiding this comment.
I don't think any of this has to do with PartialEq/Eq
There was a problem hiding this comment.
this was to fix, if I remember correctly, being able to run the nix checks against the repo. the formatter was blowing up. I can remove them.
|
I should have said that you should please feel free to include in a separate commit. If the I prefer that commit comes before the semantic changes that way each and every commit passes all of CI. |
|
@DanGould ok. i'll get them fixed up later tonight. |
|
Thanks for the perseverance. Almost there! |
12bfecc to
deeb848
Compare
deeb848 to
6078a9e
Compare
|
@DanGould okay. got the tests and lint passing finally. |
spacebear21
left a comment
There was a problem hiding this comment.
ACK 6078a9e, though there is a .Cargo.lock.flock file that snuck in, and I believe the Cargo-*.lock changes are unnecessary for this PR. Otherwise looks good to me.
|
@spacebear21 i can clean that up if desired. i think some of that happened when i was trying to get lints to pass about a month ago. |
|
@w3irdrobot please do, I'll merge this PR once that is cleaned up. |
This allows testing against specific error variants without using string matching.
6078a9e to
f18c736
Compare
|
@spacebear21 i removed that random flock file. the Cargo-*.lock changes are actually needed because the most recent version actually added the |
|
Oh I see, that makes sense. Thanks for removing the other flock file. Will re-ACK/merge pending passing CI. |
Addressed comments re: unrelated changes
There was a problem hiding this comment.
re-ACK f18c736, thanks for keeping this alive @w3irdrobot!
This one escalated quickly. There were many enums where I needed to implement
PartialEq/Eqmanually. I usedfalsein those implementations when the wrapped error did not implement these traits. The biggest change here is the change ofpayjoin::ImplementationErrorfrom a type alias to a newtype. This update required adding some implementations toImplementationErrorfrom other errors we use. To prevent adding a bunch of dependencies topayjoin, I also opted for manually wrapping errors using.map_err(ImplementationError::new)in many places instead of implementingFrom<SomeNewDependecyError> for ImplementationError. It's not necessarily the cleanest; it exposes some places for improvements in error handling. However, I assume #403 will tighten some of this up.Closes #645