-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Newtype hashbrown
#18694
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
Newtype hashbrown
#18694
Conversation
It looks like your PR is a breaking change, but you didn't provide a migration guide. Please review the instructions for writing migration guides, then expand or revise the content in the migration guides directory to reflect your changes. |
No need to copy over the inherent methods! We can just implement |
The issue is cases where a user wants to use the typename to access a method: let map = HashMap::new(); Since I have to add forwarding implementations for some methods, I just grabbed the entire public API. |
let layer_map = pointer_over_map | ||
.entry(pointer) | ||
.or_insert_with(BTreeMap::new); | ||
let layer_map = pointer_over_map.entry(pointer).or_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.
Unrelated CI failure
let spawned = self | ||
.spawned_dynamic_scenes | ||
.entry(handle.id()) | ||
.or_insert_with(HashSet::default); | ||
let spawned = self.spawned_dynamic_scenes.entry(handle.id()).or_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.
Unrelated CI failure
Good implementation and I agree with your choices but needs better docs :) It's annoying to have to do this but this is effectively a one time cost. |
Yeah since this is "Bevy's" hashmap/set implementation it does deserve better documentation. I've gone through and added at a minimum links to the underlying
Agreed. Plus we insulate ourselves from further API changes pretty strongly this way. |
I think because this PR is intended for 0.16 I should omit the migration guide in the repo? Happy to add it there if anyone disagrees tho! |
To mitigate the breaking changes fully, there should also be this impl for the wrapped And for completeness, it is nice to have |
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.
Approving on the basis that this looks to do the right thing and fix the migration issue. Thanks for the (tedious) work!
Just to note, I can't help but having that feeling that if the Rust std team didn't make HashMap::new()
use the hasher from the generic parameter, and instead force it to RandomState
, there's a reason for this choice. Is that a language limitation? Is there an edge case we're not seeing? I'd feel more comfortable with this change if we had an answer to that question first and understood the original design choice.
} | ||
} | ||
|
||
impl<K, V, S> Deref for HashMap<K, V, S> { |
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.
Curious here, can't we use a derive? Why do we have to manually impl this?
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.
Purely because this crate doesn't take a dependency on any crates that provide that derive macro. Simple enough to write so I'd rather avoid possible compile time changes.
I attempted to remove these methods (leaving only the associated functions) but there were several compilation issues I was unable to resolve. Some were due to using
Agreed! I've added both of these. |
I see, but these cases are actually useful to know! Because they should appear in the migration guide for #16912. It'd be nice to know how exactly other things broke. |
Yeah that's definitely the solution, but the goal here is to minimise the work in migrating to 0.16. Remembering that the status quo without this PR is to "just" replace
Yeah I reckon that'd be the fix.
Yeah I'm still unsure how |
We might disagree here! I see the breaking changes to construction concerning Additionally, unless we replicate every feature-specific impl, f.e. impls gated under the rayon feature, it is still a breaking change in this respect + the missing gated trait impls. If that's fine, then instead of removing these methods, we could also make a note of why the duplication exists/where the line was drawn and leave it at that.
|
Yeah I agree! I totally appreciate the position you're taking here, and I suspect our disagreement does just come down to which compromises each of us personally prefers.
This is unfortunate, but I checked the docs page with this PR, and the deref methods are separated into their own section (in the sidebar and the content of the page). Within Visual Studio Code, the duplicate methods aren't suggested by rust-analyser, so the only time you'll see these methods are when you have the proper context on docs.rs.
Yeah when you put it that way I'm convinced. I'll add
Yeah I drew a line here since Bevy otherwise has no support for these APIs (the existing type aliases had no allocator parameter, forcing users to rely on
Agreed, I've added those methods for completeness. |
I'm convinced we've found a solution with few enough trade-offs that I'm comfortable moving forward as-is. Merging :) |
# Objective - Fixes #18690 - Closes [#2065](bevyengine/bevy-website#2065) - Alternative to #18691 The changes to the Hash made in #15801 to the [BuildHasher](https://doc.rust-lang.org/std/hash/trait.BuildHasher.html) resulted in serious migration problems and downgraded UX for users of Bevy's re-exported hashmaps. Once merged, we need to go in and remove the migration guide added as part of #15801. ## Solution - Newtype `HashMap` and `HashSet` instead of type aliases - Added `Deref/Mut` to allow accessing future `hashbrown` methods without maintenance from Bevy - Added bidirectional `From` implementations to provide escape hatch for API incompatibility - Added inlinable re-exports of all methods directly to Bevy's types. This ensures `HashMap::new()` works (since the `Deref` implementation wont cover these kinds of invocations). ## Testing - CI --- ## Migration Guide - If you relied on Bevy's `HashMap` and/or `HashSet` types to be identical to `hashbrown`, consider using `From` and `Into` to convert between the `hashbrown` and Bevy types as required. - If you relied on `hashbrown/serde` or `hashbrown/rayon` features, you may need to enable `bevy_platform_support/serialize` and/or `bevy_platform_support/rayon` respectively. --- ## Notes - Did not replicate the Rayon traits, users will need to rely on the `Deref/Mut` or `From` implementations for those methods. - Did not re-expose the `unsafe` methods from `hashbrown`. In most cases users will still have access via `Deref/Mut` anyway. - I have added `inline` to all methods as they are trivial wrappings of existing methods. - I chose to make `HashMap::new` and `HashSet::new` const, which is different to `hashbrown`. We can do this because we default to a fixed-state build-hasher. Mild ergonomic win over using `HashMap::with_hasher(FixedHasher)`.
During the migration to 0.16, I added a few workarounds related to `hashbrown` to make the code compile. These issues have been fixed in the latest Bevy RC: bevyengine/bevy#18694 So we can now remove those workarounds.
During the migration to 0.16, I added a few workarounds related to `hashbrown` to make the code compile. These issues have been fixed in the latest Bevy RC: bevyengine/bevy#18694 So we can now remove those workarounds.
Objective
The changes to the Hash made in #15801 to the BuildHasher resulted in serious migration problems and downgraded UX for users of Bevy's re-exported hashmaps. Once merged, we need to go in and remove the migration guide added as part of #15801.
Solution
HashMap
andHashSet
instead of type aliasesDeref/Mut
to allow accessing futurehashbrown
methods without maintenance from BevyFrom
implementations to provide escape hatch for API incompatibilityHashMap::new()
works (since theDeref
implementation wont cover these kinds of invocations).Testing
Migration Guide
HashMap
and/orHashSet
types to be identical tohashbrown
, consider usingFrom
andInto
to convert between thehashbrown
and Bevy types as required.hashbrown/serde
orhashbrown/rayon
features, you may need to enablebevy_platform_support/serialize
and/orbevy_platform_support/rayon
respectively.Notes
Deref/Mut
orFrom
implementations for those methods.unsafe
methods fromhashbrown
. In most cases users will still have access viaDeref/Mut
anyway.inline
to all methods as they are trivial wrappings of existing methods.HashMap::new
andHashSet::new
const, which is different tohashbrown
. We can do this because we default to a fixed-state build-hasher. Mild ergonomic win over usingHashMap::with_hasher(FixedHasher)
.