Skip to content

Commit b039bf6

Browse files
authored
implement UniqueEntityVec (#17549)
# Objective In #16547, we added `EntitySet`s/`EntitySetIterator`s. We can know whenever an iterator only contains unique entities, however we do not yet have the ability to collect and reuse these without either the unsafe `UniqueEntityIter::from_iterator_unchecked`, or the expensive `HashSet::from_iter`. An important piece for being able to do this is a `Vec` that maintains the uniqueness property, can be collected into, and is itself `EntitySet`. A lot of entity collections are already intended to be "unique", but have no way of expressing that when stored, other than using an aforementioned `HashSet`. Such a type helps by limiting or even removing the need for unsafe on the user side when not using a validated `Set` type, and makes it easier to interface with other infrastructure like f.e. `RelationshipSourceCollection`s. ## Solution We implement `UniqueEntityVec`. This is a wrapper around `Vec`, that only ever contains unique elements. It mirrors the API of `Vec`, however restricts any mutation as to not violate the uniqueness guarantee. Meaning: - Any inherent method which can introduce new elements or mutate existing ones is now unsafe, f.e.: `insert`, `retain_mut` - Methods that are impossible to use safely are omitted, f.e.: `fill`, `extend_from_within` A handful of the unsafe methods can do element-wise mutation (`retain_mut`, `dedup_by`), which can be an unwind safety hazard were the element-wise operation to panic. For those methods, we require that each individual execution of the operation upholds uniqueness, not just the entire method as a whole. To be safe for mutable usage, slicing and the associated slice methods require a matching `UniqueEntitySlice` type , which we leave for a follow-up PR. Because this type will deref into the `UniqueEntitySlice` type, we also offer the immutable `Vec` methods on this type (which only amount to a handful). "as inner" functionality is covered by additional `as_vec`/`as_mut_vec` methods + `AsRef`/`Borrow` trait impls. Like `UniqueEntityIter::from_iterator_unchecked`, this type has a `from_vec_unchecked` method as well. The canonical way to safely obtain this type however is via `EntitySetIterator::collect_set` or `UniqueEntityVec::from_entity_set_iter`. Like mentioned in #17513, these are named suboptimally until supertrait item shadowing arrives, since a normal `collect` will still run equality checks.
1 parent b25bbb7 commit b039bf6

File tree

3 files changed

+743
-0
lines changed

3 files changed

+743
-0
lines changed

crates/bevy_ecs/clippy.toml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
disallowed-methods = [
2+
{ path = "UniqueEntityVec::from_iter", reason = "Use UniqueEntityVec::from_entity_set_iter if possible, it skips validation" },
3+
{ path = "EntitySetIterator::collect::<UniqueEntityVec>", reason = "Use EntitySetIterator::collect_set if possible, it skips validation" },
4+
]

crates/bevy_ecs/src/entity/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pub use entity_set::*;
5050
pub use map_entities::*;
5151
pub use visit_entities::*;
5252

53+
mod unique_vec;
54+
55+
pub use unique_vec::*;
56+
5357
mod hash;
5458
pub use hash::*;
5559

0 commit comments

Comments
 (0)