-
Notifications
You must be signed in to change notification settings - Fork 228
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
[fixed-hash] Major overhaul of construct_hash!
macro
#71
Conversation
Deref and DerefMut are only meant to be used by smart pointer types. Hash types as provided by this crate are no smart pointers and thus shouldn't provide Deref or DerefMut impls.
The AsRef<Self> impl is causing problems in generic code because the compiler fails to infer types because of it due to the other more useful AsRef and AsMut impls.
These methods are very similar to the ones provides by std implementations such as String::as_str that are also provided besides String::as_ref impl. This commit just mirrors this design decision. An advantage is that there is no type confusion on caller code with these new methods.
The compile errors were direct results of the API changes of the latest commits.
The macro now allows a more standard interface to constructing new types compared to before which is proposed by the Rust API guidelines.
Also added some more examples of new use cases possible by the new interface. Those include - private/public type definition - adding custom doc comment for the type - having more standard type definition
Using paths that were beginning with `::foo` had a wrong crate as root during the doc tests. Manually adding `$crate::foo` to all of them fixed the bugs and we can now successfully test those macros in doc comments. Special thanks to Sergei for pointing $crate out to me!
It looks like @Robbepop signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
As far as I can tell the build failures reported by TravisCI and Appveyor are not related to |
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.
Looks pretty cool, would be nice to have a similar overhaul for uint
as well, as both types have some commonalities (at least in the way we use them in Parity products).
@tomusdrw Thank you for the feedback! I have found some other things in the crate that could be improved. This is because all Read more: https://doc.rust-lang.org/std/mem/fn.size_of.html#size-of-reprc-items I didn't fix it since this PR is already pretty big but in the end it should be fixed as well before we release another major version of the |
Macro matcher of macro_rules! construct_hash.
The macro no longer requires inputs of the type's sizes since they can be easily infered without overhead thus making this API much more easy to use. Also greatly improved the documentation and added a usage example for the new API.
The only single usage of it got replaced inline manually.
TravisCI and Appveyor are showing errors because of this issues which seems to be unrelated to the work in this PR. |
construct_hash!
macroconstruct_hash!
macro
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.
Much better docs&examples, and I like the type visibility changes (although: nightly only is a no-no for this to be merged). Tests are failing and I'm not sure exactly why.
The feature set listed in Cargo.toml
looks odd (not this PRs fault, but worth fixing if we're introducing breaking changes) and plain wrong (e.g. we don't have any serde code).
Past experience tells me new issues tend to pop up we start using the parity-common
crates in parity-ethereum
or wherever they're used; it'd be fantastic if you could start a PR in the projects that use fixed-hash
to make sure the changes work well there. This crate in particular should work as a replacement for parity-hash
so it'd be good to check what needs to be done for that to happen as well.
fixed-hash/src/hash.rs
Outdated
($large_ty:ident, $small_ty:ident) => { | ||
impl From<$small_ty> for $large_ty { | ||
fn from(value: $small_ty) -> $large_ty { | ||
use std::mem; |
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.
Something fishy is going on with this macro; on this branch I get warnings about missing std. If the conversions need to work in both std
/no_std
we should use core::mem
(and sort out the implications in lib.rs
). I also get a bunch of type mismatch
test failures when enabling this feature.
In the PR description you mentioned "testing in isolation". Not sure what you meant by that exactly but I copied the files out of parity-common
and fixed up Cargo.toml
and ran the tests: same failures. Can you elaborate further on this aspect?
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.
The use std::mem;
is probably wrong here and should be replaced with use $crate::core::mem
are you have suggested I guess. Besides that I will look into the problems you have had.
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.
Unfortunately I can't find where I have written something about "testing in isolation" and can't remember either. :(
I hope the GitHub downtime is over soon and things are syncing again correctly.
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.
To verify that yourself you can try to test this crate in isolation locally.
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.
@pepyakin and me were trying to find a solution together.
The solution is to include the "std"
feature in the default
features.
This means that you have to build the crate with the cargo flag --no-default-features
for a proper no_std
environment. Fortunately this fixes the problems with doc tests above.
Also note that this is how it is done in other no_std
crates in the pwasm-*
area.
This crate now generates a useful ApiDummy hash type for the purpose of API inspection at docs.rs. Also the Cargo.toml now refers to the documentation that is going to be generated at docs.rs once uploaded to crates.io.
Deprecated since this crate no longer supports interoperability with uint in version 0.3. This support has to be provided from the outside, like pwasm-std.
.travis.yml
Outdated
@@ -9,7 +9,7 @@ script: | |||
- cargo check --all --tests | |||
- cargo build --all | |||
- cargo test --all --exclude uint --exclude fixed-hash | |||
- cd fixed-hash/ && cargo test --features=std,heapsizeof,uint_conversions && cd .. | |||
- cd fixed-hash/ && cargo test --features=quickcheck-support,heapsize-support && cd .. |
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 does not run all tests I think (24 vs 37). Should perhaps be cargo test --all-features
?
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.
Good idea!
serde = { version = "1.0", optional = true } | ||
serde_derive = { version = "1.0", optional = true } | ||
rand = { version = "0.5", optional = true, default-features = false } | ||
rustc-hex = { version = "2.0", optional = true, default-features = false } |
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.
I kind of wish we could get rid of this dependency; I don't think it buys us much ergonomics. One day perhaps...
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.
Well we could disable its feature guard by default.
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.
From what I've seen in other places rustc-hex
is all over the place so doing that would be quite some (boring) work. Probably not something we have time for right now... :)
fixed-hash/Cargo.toml
Outdated
rand = { version = "0.5", optional = true, default-features = false } | ||
rustc-hex = { version = "2.0", optional = true, default-features = false } | ||
quickcheck = { version = "0.7", optional = true } | ||
byteorder = { version = "1.2.7", optional = true, default-features = false } |
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 we use version = "1.2"
here?
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.
we can
serialize = ["serde", "serde_derive"] | ||
uint_conversions = ["uint"] | ||
default = ["std", "libc", "rand-support", "rustc-hex-support", "byteorder-support"] | ||
std = ["rustc-hex/std", "rand/std", "byteorder/std"] |
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.
I think this can be just:
default = ["std"]
std = ["rustc-hex/std", "rand/std", "byteorder/std", "libc"]
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.
So you say that all of those features should be disabled by default? I can do that but in my opinion it is always a good thing to have the common uses active by default. This is for example byteorder-support
and I would even say rustc-hex-support
.
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.
No, that's not what I meant. I think that by having rand/std
you tell cargo to "use the rand feature and use it with the std feature of rand enabled", i.e. default = ["std"]
implies that rustc-hex
, rand
and byteorder
will all be enabled (and will all be configured to use their respective std
feature). Do double-check me on that though, I'm not 100% sure!
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.
The problem is that this requires not having rand
, byteorder
and rustc-hex
being activated but their features rand-support
, byteorder-support
and rustc-hex-support
should be enabled since the entire code is guarded by them and not by their respective features which is more accurate I think. So this would cause problems I think.
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.
Btw.: I think the normal use case is to either use std
feature or libc
but not both at the same time. So implying the one by the other seems to be wrong to me. But I might be confused about that!
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl Copy for $from {} | ||
impl $crate::core::marker::Copy for $name {} |
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.
Would it be crazy to make this optional? I.e. to let consumers decide if they want their hash type to be Copy
or rather use move semantics? cc @debris
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.
Maybe we could even do this with the simple addition of attributes via #[derive(Copy)]
on the user side. This would be pretty cool. :)
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.
According to the Copy
reference we should keep the behaviour of implementing Copy
by default for all hash types: https://doc.rust-lang.org/std/marker/trait.Copy.html#when-should-my-type-be-copy
impl Clone for $from { | ||
fn clone(&self) -> $from { | ||
let mut ret = $from::new(); | ||
#[cfg_attr(feature = "dev", allow(expl_impl_clone_on_copy))] |
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.
There is no dev
feature I think? Can we remove this code perhaps?
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 from an old revision and to be honest I thought that the dev
feature is something magical. But ofc we can remove it if it doesn't exist at all.
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.
@debris do you know the origin of features="dev"
per chance?
ret | ||
/// Utilities using the `rand` crate. | ||
#[cfg(feature = "rand-support")] | ||
impl $name { |
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.
Here too there's an expansion of the API and while the code looks great I'm a bit hesitant to add new public methods like this without knowing more about which projects are going to use them. Can you elaborate?
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.
I can understand your critics about expanding the API. I just did the same as I have done already in my crate apint
. There the rand
-based API is a good addition and allows for easy testing with the *_using
APIs and allows for user friendly usage by the APIs with the default RNG. :)
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.
Keep in mind that the rand
API existed earlier but wasn't testable since it was missing the *_using
methods. So basically the new API allows for greater control and better testability.
|
||
/// Implements conversion to and from a hash type and the equally sized unsigned int. | ||
/// CAUTION: Bad things will happen if the two types are not of the same size! | ||
#[cfg(feature="uint_conversions")] |
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.
What is the plan for these? Move them to uint
? Own crate? Just remove them? They are currently in use in ethereum-types
so we need some kind of upgrade path for consumers.
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.
I had the idea to move them to pwasm-std
for the pwasm-*
crates and also provide uint
types by pwasm-std
so it fits again for it. And for ethereum-types
I would do the same I guess. Maybe just another crate to unify both? It actually is not feasible to make uint
depending on fixed-hash
since it is built up from u64
words instead of bytes and would require another major overhaul. However, uint
is far more complex than fixed-hash
.
So to summarize: The best way is to have this functionality in the crate that actually needs this interoperability or in another small utility crate featuring both types.
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.
Hmm, a tricky one! My personal opinion is that it's probably less disruptive/more pragmatic to just keep these conversions in fixed-hash
for the time being and refactor later – maybe we can make the consuming code use the conversions less or not at all and we can just remove this? If you feel strongly this is not a good path ahead, I can be swayed though (though we can't merge before we have a solution to this as it'd make upgrading impossible).
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.
I am not strongly against having the conversions in fixed-hash
as a conversion path to a better future. However, I do not see anyone of us implementing this better future anytime soon if we stay with this approach. :D
This now just tests the same things as travis CI.
This should avoid more name collission and is also more clear that the macro is linked to the `fixed-hash` crate.
Could be used by uint conversion to avoid length checks.
fixed-hash/src/hash.rs
Outdated
feature = "libc", | ||
not(target_os = "unknown") | ||
))] | ||
#[cfg(feature = "heapsize-support")] |
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.
The target_os
need to be there I'm afraid. WASM can't use the heapsize
crate.
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.
okay will revert it
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.
done
Seems like heapsize needs libc and target_os = "unknown" settings.
LGTM. Great work and perseverence here @Robbepop! Many thanks. |
Overhaul of the entire sub-crate
fixed-hash
Roadmap
Pre-merging
Sort out the last few nits with new features
Merge this PR after
Bump version to
0.3-beta.0
and publish on crates.io.Post-merging
Transit all below dependencies to the
0.3.0-beta.X
version offixed-hash
. Note that thepwasm-*
crates currently depend onparity-hash
instead offixed-hash
version0.2
.pwasm-std
will provide newuint
instances and updatedfixed-hash
instances without conversion betweenuint
andfixed-hash
since I cannot see that it has been provided yetpwasm-ethereum
will no longer link toparity-hash
and instead usepwasm-std
pwasm-abi
same aspwasm-ethereum
ethbloom
simply updatefixed-hash
ethereum-types
updatefixed-hash
, but already providesuint
conversions itself, so no need for providing them byfixed-hash
eithersubstrate-primitives
updatefixed-hash
but does not needuint
conversionMake any changes that might come up during the work on step 4 and publish
0.3-beta.X
as neededBump version to
0.3
, create a tagfixed-hash-0.3
and publish0.3
Open Questions
impl_hash_uint_conversions
macro?fixed-hash
and not inuint
?fixed-hash
anduint
and allow for this macro.Summary of changes
construct_hash
macropub
)impl_hash_conversion
macrostd
feature is now a default feature for this crate0.2.5
AsRef<Self>
implserialize
crate feature