-
Notifications
You must be signed in to change notification settings - Fork 215
digest: problems with the Digest
trait
#395
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
Comments
Digest
traitDigest
trait
To be clear, I'm happy to submit a PR with my proposed changes, but I'm feeling a bit confused and wondering if I'm missing something. I'm also wondering what the requirements are for compatibility, because while there is basically no change to the actual API in my proposed changes, they may cause some (easy to fix) breakage in code that uses e.g. |
I vaguely remember that long ago I had some issues with making Though, it's a different story for |
I think the main advantage of the current setup is that consumers of the trait do not have to have all of the sub-traits in scope to use the various methods. I suppose an alternative to that would be something like
@rvolgers it sounds like you actually find the aforementioned setup preferable when all the methods are available?
It seems like this problem could also be addressed by adding a |
Ah, it was exactly this problem! It can be demonstrated using this example. Even though Ideally, I would love to have "inherent traits", which would make the |
Also note that a rationale for the current layered trait design is given in the toplevel rustdoc, although perhaps it could be improved: https://docs.rs/digest/0.9.0/digest/
|
You cannot mix |
Thanks for the explanation, I guess it is a bit inconvenient to import the mid level traits, but the IDE takes care of that for me so I personally don't mind. But this does invalidate my initial suggestions. I do think the documentation can be improved. I realize now the intention behind the word "wrapper" that is used here, but it was not at all clear to me initially. No matter how many traits you have it is still the same type, so to me it was natural to try and mix and match traits. The resulting errors can also get really strange if you are unlucky. I would still like to try to improve this experience a little, even if only by updating documentation. Concretely I would like to add some text to What I'm not going to change (because it feels like a significant change and I'm not sure I have enough time and I know I don't have enough experience with this project), but might be worth considering, is whether the high/mid/low idea is a helpful concept. If the "high level" traits became separate (trivial) wrapper structs documented as a "simplified API" and the "low-level" traits were instead described as "implementation details" I think it would help people a ton in building the right mental model for how they are expected to be used. |
Digest
traitDigest
trait
I've added the |
Uh oh!
There was an error while loading. Please reload this page.
I'm implementing a Merkle Tree based hash function, which uses an existing hash function as its base, and I ran into some annoying aspects of the
Digest
trait.The documentation describes
Digest
as a "wrapper" around various other traits, namelyUpdate
,FixedOutput
,Reset
,Clone
, andDefault
. But it is not actually a subtrait of these traits! This was very surprising to me.In fact, it duplicates some functionality of the other traits, without being an implementation of them. In particular
Digest::chain
is an exact duplicate ofUpdate::chain
,Digest::reset
is an exact duplicate ofReset::reset
,Digest::update
duplicatesUpdate::update
and the associated typeDigest::OutputSize
duplicatesFixedOutput::OutputSize
.I ran into this when I tried to use
finalize_into
on a generic bounded byDigest
. This function (which is defined inFixedOutput
) is not available onDigest
becauseDigest
does not actually implementFixedOutput
, it just requires it internally and then duplicates some of its functionality in its API (but notfinalize_into
).So, my next idea was to set the generic bound to
Digest + Update + FixedOutput + Reset
. This causes chaos though, because now there are conflicts for the nameschain
,reset
, andOutputSize
, so you have to explicitly tell Rust whether you want the one defined byDigest
or the one from the underlying trait, even though they should be the same. There was also some trouble because Rust could not see thatFixedOutput::OutputSize
andDigest::OutputSize
are equal, and I had some variables that had to match both.Finally, I decided
Digest
was not usable and I decided to simply use the underlying traits. This fixed all my problems but it's a shame to do without the convenience functions.I don't really understand why the
Digest
trait works this way.Concretely, I would suggest making
Digest
an actual subtrait of the traits it wraps, and removing the confusing duplicated functionality. This would technically be a breaking change. I would also move thedigest::Output
type alias to thefixed
module.(The
DynDigest
trait is very similar, everything I've said applies to that as well)The text was updated successfully, but these errors were encountered: