-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
make EntityHashMap and EntityHashSet proper types #16912
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
make EntityHashMap and EntityHashSet proper types #16912
Conversation
| /// /// This struct is created by the [`keys`] method on [`EntityHashMap`]. See its documentation for more. | ||
| /// | ||
| /// [`keys`]: EntityHashMap::keys | ||
| pub struct Keys<'a, V, S = EntityHash>(hash_map::Keys<'a, Entity, V>, PhantomData<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.
Why do you need the S type parameter and PhantomData? It looks like this is only ever instantiated with S = EntityHash.
(And the same question for the other types with a PhantomData.)
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 is! This S generic parameter is currently only here to express the purpose of these newtypes to the readers:
Technically a newtype alone is enough, but then the type will not communicate why it exists.
This is especially the case for the EntitySetIterator impls.
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.
In the future we might also want to support more hashers, as we currently have multiple "trusted" Hashers in the engine. However I think I'll leave that for when we support hashing more TrustedEntityBorrow types.
(That allows for switching MainEntityHashMap/Set as well)
| /// Clears the set, returning all elements in an iterator. | ||
| /// | ||
| /// Equivalent to [`HashSet::drain`]. | ||
| pub fn drain(&mut self) -> Drain<'_> { |
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.
Do you also want a wrapper for ExtractIf?
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.
yes!
alice-i-cecile
left a comment
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.
Annoying to need more code for this, but this is well-executed and I agree with the justification.
|
Yeah, all this code and the upcoming |
# Objective `EntityHashMap` and `EntityHashSet` iterators do not implement `EntitySetIterator`. ## Solution Make them newtypes instead of aliases. The methods that create the iterators can then produce their own newtypes that carry the `Hasher` generic and implement `EntitySetIterator`. Functionality remains the same otherwise. There are some other small benefits, f.e. the removal of `with_hasher` associated functions, and the ability to implement more traits ourselves. `MainEntityHashMap` and `MainEntityHashSet` are currently left as the previous type aliases, because supporting general `TrustedEntityBorrow` hashing is more complex. However, it can also be done. ## Testing Pre-existing `EntityHashMap` tests. ## Migration Guide Users of `with_hasher` and `with_capacity_and_hasher` on `EntityHashMap`/`Set` must now use `new` and `with_capacity` respectively. If the non-newtyped versions are required, they can be obtained via `Deref`, `DerefMut` or `into_inner` calls.
# Objective We do not have `EntityIndexMap`/`EntityIndexSet`. Usual `HashMap`s/`HashSet`s do not guarantee any order, which can be awkward for some use cases. The `indexmap` versions remember insertion order, which then also becomes their iteration order. They can be thought of as a `HashTable` + `Vec`, which means fast iteration and removal, indexing by index (not just key), and slicing! Performance should otherwise be comparable. ## Solution Because `indexmap` is structured to mirror `hashbrown`, it suffers the same issue of not having the `Hasher` generic on their iterators. #16912 solved this issue for `EntityHashMap`/`EntityHashSet` with a wrapper around the hashbrown version, so this PR does the same. Hopefully these wrappers can be removed again in the future by having `hashbrown`/`indexmap` adopt that generic in their iterators themselves!
# Objective #16912 turned `EntityHashMap` and `EntityHashSet` into proper newtypes instead of type aliases. However, this removed the ability to create these collections in const contexts; previously, you could use `EntityHashSet::with_hasher(EntityHash)`, but it doesn't exist anymore. ## Solution Make `EntityHashMap::new` and `EntityHashSet::new` const methods.
# Objective Follow-up to #17615. Bevy's entity collection types like `EntityHashSet` no longer implement serde's `Serialize` and `Deserialize` after becoming newtypes instead of type aliases in #16912. This broke some types that support serde for me in Avian. I also missed creating const constructors for `EntityIndexMap` and `EntityIndexSet` in #17615. Oops! ## Solution Implement `Serialize` and `Deserialize` for Bevy's entity collection types, and add const constructors for `EntityIndexMap` and `EntityIndexSet`. I didn't implement `ReflectSerialize` or `ReflectDeserialize` here, because I had some trouble fixing the resulting errors, and they were not implemented previously either.
# Objective `EntityHashMap` and `EntityHashSet` iterators do not implement `EntitySetIterator`. ## Solution Make them newtypes instead of aliases. The methods that create the iterators can then produce their own newtypes that carry the `Hasher` generic and implement `EntitySetIterator`. Functionality remains the same otherwise. There are some other small benefits, f.e. the removal of `with_hasher` associated functions, and the ability to implement more traits ourselves. `MainEntityHashMap` and `MainEntityHashSet` are currently left as the previous type aliases, because supporting general `TrustedEntityBorrow` hashing is more complex. However, it can also be done. ## Testing Pre-existing `EntityHashMap` tests. ## Migration Guide Users of `with_hasher` and `with_capacity_and_hasher` on `EntityHashMap`/`Set` must now use `new` and `with_capacity` respectively. If the non-newtyped versions are required, they can be obtained via `Deref`, `DerefMut` or `into_inner` calls.
# Objective We do not have `EntityIndexMap`/`EntityIndexSet`. Usual `HashMap`s/`HashSet`s do not guarantee any order, which can be awkward for some use cases. The `indexmap` versions remember insertion order, which then also becomes their iteration order. They can be thought of as a `HashTable` + `Vec`, which means fast iteration and removal, indexing by index (not just key), and slicing! Performance should otherwise be comparable. ## Solution Because `indexmap` is structured to mirror `hashbrown`, it suffers the same issue of not having the `Hasher` generic on their iterators. bevyengine#16912 solved this issue for `EntityHashMap`/`EntityHashSet` with a wrapper around the hashbrown version, so this PR does the same. Hopefully these wrappers can be removed again in the future by having `hashbrown`/`indexmap` adopt that generic in their iterators themselves!
…17615) # Objective bevyengine#16912 turned `EntityHashMap` and `EntityHashSet` into proper newtypes instead of type aliases. However, this removed the ability to create these collections in const contexts; previously, you could use `EntityHashSet::with_hasher(EntityHash)`, but it doesn't exist anymore. ## Solution Make `EntityHashMap::new` and `EntityHashSet::new` const methods.
…e#17620) # Objective Follow-up to bevyengine#17615. Bevy's entity collection types like `EntityHashSet` no longer implement serde's `Serialize` and `Deserialize` after becoming newtypes instead of type aliases in bevyengine#16912. This broke some types that support serde for me in Avian. I also missed creating const constructors for `EntityIndexMap` and `EntityIndexSet` in bevyengine#17615. Oops! ## Solution Implement `Serialize` and `Deserialize` for Bevy's entity collection types, and add const constructors for `EntityIndexMap` and `EntityIndexSet`. I didn't implement `ReflectSerialize` or `ReflectDeserialize` here, because I had some trouble fixing the resulting errors, and they were not implemented previously either.
…17615) # Objective bevyengine#16912 turned `EntityHashMap` and `EntityHashSet` into proper newtypes instead of type aliases. However, this removed the ability to create these collections in const contexts; previously, you could use `EntityHashSet::with_hasher(EntityHash)`, but it doesn't exist anymore. ## Solution Make `EntityHashMap::new` and `EntityHashSet::new` const methods.
…e#17620) # Objective Follow-up to bevyengine#17615. Bevy's entity collection types like `EntityHashSet` no longer implement serde's `Serialize` and `Deserialize` after becoming newtypes instead of type aliases in bevyengine#16912. This broke some types that support serde for me in Avian. I also missed creating const constructors for `EntityIndexMap` and `EntityIndexSet` in bevyengine#17615. Oops! ## Solution Implement `Serialize` and `Deserialize` for Bevy's entity collection types, and add const constructors for `EntityIndexMap` and `EntityIndexSet`. I didn't implement `ReflectSerialize` or `ReflectDeserialize` here, because I had some trouble fixing the resulting errors, and they were not implemented previously either.
Objective
EntityHashMapandEntityHashSetiterators do not implementEntitySetIterator.Solution
Make them newtypes instead of aliases. The methods that create the iterators can then produce their own newtypes that carry the
Hashergeneric and implementEntitySetIterator. Functionality remains the same otherwise.There are some other small benefits, f.e. the removal of
with_hasherassociated functions, and the ability to implement more traits ourselves.MainEntityHashMapandMainEntityHashSetare currently left as the previous type aliases, because supporting generalTrustedEntityBorrowhashing is more complex. However, it can also be done.Testing
Pre-existing
EntityHashMaptests.Migration Guide
Users of
with_hasherandwith_capacity_and_hasheronEntityHashMap/Setmust now usenewandwith_capacityrespectively.If the non-newtyped versions are required, they can be obtained via
Deref,DerefMutorinto_innercalls.