diff --git a/crates/bevy_ecs/src/entity/entity_set.rs b/crates/bevy_ecs/src/entity/entity_set.rs index e4860685fe07f..1d9bd18f7a41c 100644 --- a/crates/bevy_ecs/src/entity/entity_set.rs +++ b/crates/bevy_ecs/src/entity/entity_set.rs @@ -10,7 +10,7 @@ use core::{ fmt::{Debug, Formatter}, hash::{BuildHasher, Hash}, iter::{self, FusedIterator}, - option, result, + option, ptr, result, }; use super::{Entity, UniqueEntityEquivalentSlice}; @@ -58,7 +58,7 @@ pub trait ContainsEntity { /// To obtain hash values forming the same total order as [`Entity`], any [`Hasher`] used must be /// deterministic and concerning [`Entity`], collisionless. /// Standard library hash collections handle collisions with an [`Eq`] fallback, but do not account for -/// determinism when [`BuildHasher`] is unspecified,. +/// determinism when [`BuildHasher`] is unspecified. /// /// [`Hash`]: core::hash::Hash /// [`Hasher`]: core::hash::Hasher @@ -143,12 +143,12 @@ unsafe impl EntityEquivalent for Arc {} /// As a consequence, [`into_iter()`] on `EntitySet` will always produce another `EntitySet`. /// /// Implementing this trait allows for unique query iteration over a list of entities. -/// See [`iter_many_unique`] and [`iter_many_unique_mut`] +/// See [`iter_many_unique`] and [`iter_many_unique_mut`]. /// /// Note that there is no guarantee of the [`IntoIterator`] impl being deterministic, /// it might return different iterators when called multiple times. /// Neither is there a guarantee that the comparison trait impls of `EntitySet` match that -/// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements) +/// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements). /// /// [`Self::IntoIter`]: IntoIterator::IntoIter /// [`into_iter()`]: IntoIterator::into_iter @@ -342,9 +342,10 @@ pub trait FromEntitySetIterator: FromIterator { impl FromEntitySetIterator for HashSet { + #[inline] fn from_entity_set_iter>(set_iter: I) -> Self { let iter = set_iter.into_iter(); - let set = HashSet::::with_capacity_and_hasher(iter.size_hint().0, S::default()); + let set = HashSet::with_capacity_and_hasher(iter.size_hint().0, S::default()); iter.fold(set, |mut set, e| { // SAFETY: Every element in self is unique. unsafe { @@ -358,14 +359,17 @@ impl FromEntitySetIterator /// An iterator that yields unique entities. /// /// This wrapper can provide an [`EntitySetIterator`] implementation when an instance of `I` is known to uphold uniqueness. +#[repr(transparent)] pub struct UniqueEntityIter> { iter: I, } impl UniqueEntityIter { /// Constructs a `UniqueEntityIter` from an [`EntitySetIterator`]. - pub fn from_entity_set_iterator(iter: I) -> Self { - Self { iter } + #[inline] + pub const fn from_entity_set_iter(iter: I) -> Self { + // SAFETY: iter implements `EntitySetIterator`. + unsafe { Self::from_iter_unchecked(iter) } } } @@ -375,17 +379,40 @@ impl> UniqueEntityIter { /// # Safety /// `iter` must only yield unique elements. /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. - pub unsafe fn from_iterator_unchecked(iter: I) -> Self { + #[inline] + pub const unsafe fn from_iter_unchecked(iter: I) -> Self { Self { iter } } + /// Constructs a [`UniqueEntityIter`] from an iterator unsafely. + /// + /// # Safety + /// `iter` must only yield unique elements. + /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. + #[inline] + pub const unsafe fn from_iter_ref_unchecked(iter: &I) -> &Self { + // SAFETY: UniqueEntityIter is a transparent wrapper around I. + unsafe { &*ptr::from_ref(iter).cast() } + } + + /// Constructs a [`UniqueEntityIter`] from an iterator unsafely. + /// + /// # Safety + /// `iter` must only yield unique elements. + /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. + #[inline] + pub const unsafe fn from_iter_mut_unchecked(iter: &mut I) -> &mut Self { + // SAFETY: UniqueEntityIter is a transparent wrapper around I. + unsafe { &mut *ptr::from_mut(iter).cast() } + } + /// Returns the inner `I`. pub fn into_inner(self) -> I { self.iter } /// Returns a reference to the inner `I`. - pub fn as_inner(&self) -> &I { + pub const fn as_inner(&self) -> &I { &self.iter } @@ -395,7 +422,7 @@ impl> UniqueEntityIter { /// /// `self` must always contain an iterator that yields unique elements, /// even while this reference is live. - pub unsafe fn as_mut_inner(&mut self) -> &mut I { + pub const unsafe fn as_mut_inner(&mut self) -> &mut I { &mut self.iter } } @@ -415,6 +442,7 @@ impl> Iterator for UniqueEntityIter { impl> ExactSizeIterator for UniqueEntityIter {} impl> DoubleEndedIterator for UniqueEntityIter { + #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() } @@ -506,7 +534,7 @@ mod tests { // SAFETY: SpawnBatchIter is `EntitySetIterator`, let mut unique_entity_iter = - unsafe { UniqueEntityIter::from_iterator_unchecked(spawn_batch.iter()) }; + unsafe { UniqueEntityIter::from_iter_unchecked(spawn_batch.iter()) }; let entity_set = unique_entity_iter .by_ref() diff --git a/crates/bevy_ecs/src/entity/hash.rs b/crates/bevy_ecs/src/entity/hash.rs index a53847343952a..179443fb0b20b 100644 --- a/crates/bevy_ecs/src/entity/hash.rs +++ b/crates/bevy_ecs/src/entity/hash.rs @@ -11,6 +11,7 @@ pub struct EntityHash; impl BuildHasher for EntityHash { type Hasher = EntityHasher; + #[inline] fn build_hasher(&self) -> Self::Hasher { Self::Hasher::default() } diff --git a/crates/bevy_ecs/src/entity/hash_map.rs b/crates/bevy_ecs/src/entity/hash_map.rs index 505cc440f117f..49b27ca5ab10c 100644 --- a/crates/bevy_ecs/src/entity/hash_map.rs +++ b/crates/bevy_ecs/src/entity/hash_map.rs @@ -19,7 +19,7 @@ use super::{Entity, EntityEquivalent, EntityHash, EntitySetIterator}; #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone, PartialEq, Eq)] -pub struct EntityHashMap(pub(crate) HashMap); +pub struct EntityHashMap(HashMap); impl EntityHashMap { /// Creates an empty `EntityHashMap`. @@ -35,11 +35,16 @@ impl EntityHashMap { /// /// Equivalent to [`HashMap::with_capacity_and_hasher(n, EntityHash)`]. /// - /// [`HashMap:with_capacity_and_hasher(n, EntityHash)`]: HashMap::with_capacity_and_hasher + /// [`HashMap::with_capacity_and_hasher(n, EntityHash)`]: HashMap::with_capacity_and_hasher pub fn with_capacity(n: usize) -> Self { Self(HashMap::with_capacity_and_hasher(n, EntityHash)) } + /// Constructs an `EntityHashMap` from an [`HashMap`]. + pub const fn from_index_map(set: HashMap) -> Self { + Self(set) + } + /// Returns the inner [`HashMap`]. pub fn into_inner(self) -> HashMap { self.0 @@ -113,8 +118,15 @@ impl FromIterator<(Entity, V)> for EntityHashMap { } } +impl From> for EntityHashMap { + fn from(value: HashMap) -> Self { + Self(value) + } +} + impl Index<&Q> for EntityHashMap { type Output = V; + fn index(&self, key: &Q) -> &V { self.0.index(&key.entity()) } @@ -156,8 +168,20 @@ impl IntoIterator for EntityHashMap { pub struct Keys<'a, V, S = EntityHash>(hash_map::Keys<'a, Entity, V>, PhantomData); impl<'a, V> Keys<'a, V> { + /// Constructs a [`Keys<'a, V, S>`] from a [`hash_map::Keys<'a, V>`] unsafely. + /// + /// # Safety + /// + /// `keys` must either be empty, or have been obtained from a + /// [`hash_map::HashMap`] using the `S` hasher. + pub const unsafe fn from_keys_unchecked( + keys: hash_map::Keys<'a, Entity, V>, + ) -> Keys<'a, V, S> { + Keys(keys, PhantomData) + } + /// Returns the inner [`Keys`](hash_map::Keys). - pub fn into_inner(self) -> hash_map::Keys<'a, Entity, V> { + pub const fn into_inner(self) -> hash_map::Keys<'a, Entity, V> { self.0 } } @@ -188,7 +212,8 @@ impl FusedIterator for Keys<'_, V> {} impl Clone for Keys<'_, V> { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `Keys`. + unsafe { Self::from_keys_unchecked(self.0.clone()) } } } @@ -200,7 +225,8 @@ impl Debug for Keys<'_, V> { impl Default for Keys<'_, V> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `Keys` is empty. + unsafe { Self::from_keys_unchecked(Default::default()) } } } @@ -218,6 +244,18 @@ unsafe impl EntitySetIterator for Keys<'_, V> {} pub struct IntoKeys(hash_map::IntoKeys, PhantomData); impl IntoKeys { + /// Constructs a [`IntoKeys`] from a [`hash_map::IntoKeys`] unsafely. + /// + /// # Safety + /// + /// `into_keys` must either be empty, or have been obtained from a + /// [`hash_map::HashMap`] using the `S` hasher. + pub const unsafe fn from_into_keys_unchecked( + into_keys: hash_map::IntoKeys, + ) -> IntoKeys { + IntoKeys(into_keys, PhantomData) + } + /// Returns the inner [`IntoKeys`](hash_map::IntoKeys). pub fn into_inner(self) -> hash_map::IntoKeys { self.0 @@ -259,7 +297,8 @@ impl Debug for IntoKeys { impl Default for IntoKeys { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IntoKeys` is empty. + unsafe { Self::from_into_keys_unchecked(Default::default()) } } } diff --git a/crates/bevy_ecs/src/entity/hash_set.rs b/crates/bevy_ecs/src/entity/hash_set.rs index 8b2e5927e813e..1af2a4b659f23 100644 --- a/crates/bevy_ecs/src/entity/hash_set.rs +++ b/crates/bevy_ecs/src/entity/hash_set.rs @@ -22,7 +22,7 @@ use super::{Entity, EntityHash, EntitySet, EntitySetIterator, FromEntitySetItera #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct EntityHashSet(pub(crate) HashSet); +pub struct EntityHashSet(HashSet); impl EntityHashSet { /// Creates an empty `EntityHashSet`. @@ -43,16 +43,16 @@ impl EntityHashSet { Self(HashSet::with_capacity_and_hasher(n, EntityHash)) } - /// Returns the number of elements in the set. - pub fn len(&self) -> usize { - self.0.len() - } - /// Returns `true` if the set contains no elements. pub fn is_empty(&self) -> bool { self.0.is_empty() } + /// Constructs an `EntityHashSet` from an [`HashSet`]. + pub const fn from_hash_set(set: HashSet) -> Self { + Self(set) + } + /// Returns the inner [`HashSet`]. pub fn into_inner(self) -> HashSet { self.0 @@ -210,6 +210,12 @@ impl FromEntitySetIterator for EntityHashSet { } } +impl From> for EntityHashSet { + fn from(value: HashSet) -> Self { + Self(value) + } +} + /// An iterator over the items of an [`EntityHashSet`]. /// /// This struct is created by the [`iter`] method on [`EntityHashSet`]. See its documentation for more. @@ -218,8 +224,18 @@ impl FromEntitySetIterator for EntityHashSet { pub struct Iter<'a, S = EntityHash>(hash_set::Iter<'a, Entity>, PhantomData); impl<'a> Iter<'a> { + /// Constructs a [`Iter<'a, S>`] from a [`hash_set::Iter<'a>`] unsafely. + /// + /// # Safety + /// + /// `iter` must either be empty, or have been obtained from a + /// [`hash_set::HashSet`] using the `S` hasher. + pub const unsafe fn from_iter_unchecked(iter: hash_set::Iter<'a, Entity>) -> Iter<'a, S> { + Iter(iter, PhantomData) + } + /// Returns the inner [`Iter`](hash_set::Iter). - pub fn into_inner(self) -> hash_set::Iter<'a, Entity> { + pub const fn into_inner(self) -> hash_set::Iter<'a, Entity> { self.0 } } @@ -250,7 +266,8 @@ impl FusedIterator for Iter<'_> {} impl Clone for Iter<'_> { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `Iter`. + unsafe { Self::from_iter_unchecked(self.0.clone()) } } } @@ -262,7 +279,8 @@ impl Debug for Iter<'_> { impl Default for Iter<'_> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `Iter` is empty. + unsafe { Self::from_iter_unchecked(Default::default()) } } } @@ -277,6 +295,18 @@ unsafe impl EntitySetIterator for Iter<'_> {} pub struct IntoIter(hash_set::IntoIter, PhantomData); impl IntoIter { + /// Constructs a [`IntoIter`] from a [`hash_set::IntoIter`] unsafely. + /// + /// # Safety + /// + /// `into_iter` must either be empty, or have been obtained from a + /// [`hash_set::HashSet`] using the `S` hasher. + pub const unsafe fn from_into_iter_unchecked( + into_iter: hash_set::IntoIter, + ) -> IntoIter { + IntoIter(into_iter, PhantomData) + } + /// Returns the inner [`IntoIter`](hash_set::IntoIter). pub fn into_inner(self) -> hash_set::IntoIter { self.0 @@ -318,7 +348,8 @@ impl Debug for IntoIter { impl Default for IntoIter { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IntoIter` is empty. + unsafe { Self::from_into_iter_unchecked(Default::default()) } } } @@ -333,6 +364,18 @@ unsafe impl EntitySetIterator for IntoIter {} pub struct Drain<'a, S = EntityHash>(hash_set::Drain<'a, Entity>, PhantomData); impl<'a> Drain<'a> { + /// Constructs a [`Drain<'a, S>`] from a [`hash_set::Drain<'a>`] unsafely. + /// + /// # Safety + /// + /// `drain` must either be empty, or have been obtained from a + /// [`hash_set::HashSet`] using the `S` hasher. + pub const unsafe fn from_drain_unchecked( + drain: hash_set::Drain<'a, Entity>, + ) -> Drain<'a, S> { + Drain(drain, PhantomData) + } + /// Returns the inner [`Drain`](hash_set::Drain). pub fn into_inner(self) -> hash_set::Drain<'a, Entity> { self.0 @@ -386,6 +429,18 @@ pub struct ExtractIf<'a, F: FnMut(&Entity) -> bool, S = EntityHash>( ); impl<'a, F: FnMut(&Entity) -> bool> ExtractIf<'a, F> { + /// Constructs a [`ExtractIf<'a, F, S>`] from a [`hash_set::ExtractIf<'a, F>`] unsafely. + /// + /// # Safety + /// + /// `extract_if` must either be empty, or have been obtained from a + /// [`hash_set::HashSet`] using the `S` hasher. + pub const unsafe fn from_extract_if_unchecked( + extract_if: hash_set::ExtractIf<'a, Entity, F>, + ) -> ExtractIf<'a, F, S> { + ExtractIf(extract_if, PhantomData) + } + /// Returns the inner [`ExtractIf`](hash_set::ExtractIf). pub fn into_inner(self) -> hash_set::ExtractIf<'a, Entity, F> { self.0 diff --git a/crates/bevy_ecs/src/entity/index_map.rs b/crates/bevy_ecs/src/entity/index_map.rs index 1afd28c12b2a8..350cc7f963c18 100644 --- a/crates/bevy_ecs/src/entity/index_map.rs +++ b/crates/bevy_ecs/src/entity/index_map.rs @@ -18,7 +18,11 @@ use core::{ #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; pub use indexmap::map::Entry; -use indexmap::map::{self, IndexMap, IntoValues, ValuesMut}; +use indexmap::{ + self, + map::{self, IntoValues, ValuesMut}, + IndexMap, +}; use super::{Entity, EntityEquivalent, EntityHash, EntitySetIterator}; @@ -28,14 +32,14 @@ use bevy_platform::prelude::Box; #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone)] -pub struct EntityIndexMap(pub(crate) IndexMap); +pub struct EntityIndexMap(IndexMap); impl EntityIndexMap { /// Creates an empty `EntityIndexMap`. /// /// Equivalent to [`IndexMap::with_hasher(EntityHash)`]. /// - /// [`IndexMap::with_hasher(EntityHash)`]: IndexMap::with_hasher + /// [`IndexMap::with_hasher(EntityHash)`]: indexmap::IndexMap::with_hasher pub const fn new() -> Self { Self(IndexMap::with_hasher(EntityHash)) } @@ -44,11 +48,16 @@ impl EntityIndexMap { /// /// Equivalent to [`IndexMap::with_capacity_and_hasher(n, EntityHash)`]. /// - /// [`IndexMap:with_capacity_and_hasher(n, EntityHash)`]: IndexMap::with_capacity_and_hasher + /// [`IndexMap::with_capacity_and_hasher(n, EntityHash)`]: indexmap::IndexMap::with_capacity_and_hasher pub fn with_capacity(n: usize) -> Self { Self(IndexMap::with_capacity_and_hasher(n, EntityHash)) } + /// Constructs an `EntityIndexMap` from an [`IndexMap`]. + pub const fn from_index_map(set: IndexMap) -> Self { + Self(set) + } + /// Returns the inner [`IndexMap`]. pub fn into_inner(self) -> IndexMap { self.0 @@ -179,6 +188,7 @@ impl FromIterator<(Entity, V)> for EntityIndexMap { impl Index<&Q> for EntityIndexMap { type Output = V; + fn index(&self, key: &Q) -> &V { self.0.index(&key.entity()) } @@ -186,6 +196,7 @@ impl Index<&Q> for EntityIndexMap { impl Index<(Bound, Bound)> for EntityIndexMap { type Output = Slice; + fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -194,6 +205,7 @@ impl Index<(Bound, Bound)> for EntityIndexMap { impl Index> for EntityIndexMap { type Output = Slice; + fn index(&self, key: Range) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -202,6 +214,7 @@ impl Index> for EntityIndexMap { impl Index> for EntityIndexMap { type Output = Slice; + fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -210,6 +223,7 @@ impl Index> for EntityIndexMap { impl Index for EntityIndexMap { type Output = Slice; + fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -218,6 +232,7 @@ impl Index for EntityIndexMap { impl Index> for EntityIndexMap { type Output = Slice; + fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -226,6 +241,7 @@ impl Index> for EntityIndexMap { impl Index> for EntityIndexMap { type Output = Slice; + fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -234,6 +250,7 @@ impl Index> for EntityIndexMap { impl Index> for EntityIndexMap { type Output = Slice; + fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -242,6 +259,7 @@ impl Index> for EntityIndexMap { impl Index for EntityIndexMap { type Output = V; + fn index(&self, key: usize) -> &V { self.0.index(key) } @@ -426,7 +444,7 @@ impl Slice { clippy::borrowed_box, reason = "We wish to access the Box API of the inner type, without consuming it." )] - pub fn as_boxed_inner(self: &Box) -> &Box> { + pub const fn as_boxed_inner(self: &Box) -> &Box> { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { &*(ptr::from_ref(self).cast::>>()) } } @@ -710,6 +728,7 @@ impl Eq for Slice {} impl Index<(Bound, Bound)> for Slice { type Output = Self; + fn index(&self, key: (Bound, Bound)) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -718,6 +737,7 @@ impl Index<(Bound, Bound)> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: Range) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -726,6 +746,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeFrom) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -734,6 +755,7 @@ impl Index> for Slice { impl Index for Slice { type Output = Self; + fn index(&self, key: RangeFull) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -742,6 +764,7 @@ impl Index for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -750,6 +773,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeTo) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -758,6 +782,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeToInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -766,6 +791,7 @@ impl Index> for Slice { impl Index for Slice { type Output = V; + fn index(&self, key: usize) -> &V { self.1.index(key) } @@ -833,8 +859,18 @@ impl IndexMut for Slice { pub struct Iter<'a, V, S = EntityHash>(map::Iter<'a, Entity, V>, PhantomData); impl<'a, V> Iter<'a, V> { + /// Constructs a [`Iter<'a, V, S>`] from a [`map::Iter<'a, V>`] unsafely. + /// + /// # Safety + /// + /// `iter` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_iter_unchecked(iter: map::Iter<'a, Entity, V>) -> Iter<'a, V, S> { + Iter(iter, PhantomData) + } + /// Returns the inner [`Iter`](map::Iter). - pub fn into_inner(self) -> map::Iter<'a, Entity, V> { + pub const fn into_inner(self) -> map::Iter<'a, Entity, V> { self.0 } @@ -879,7 +915,8 @@ impl FusedIterator for Iter<'_, V> {} impl Clone for Iter<'_, V> { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `Iter`. + unsafe { Self::from_iter_unchecked(self.0.clone()) } } } @@ -891,7 +928,8 @@ impl Debug for Iter<'_, V> { impl Default for Iter<'_, V> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `Iter` is empty. + unsafe { Self::from_iter_unchecked(Default::default()) } } } @@ -902,8 +940,20 @@ impl Default for Iter<'_, V> { pub struct IterMut<'a, V, S = EntityHash>(map::IterMut<'a, Entity, V>, PhantomData); impl<'a, V> IterMut<'a, V> { + /// Constructs a [`IterMut<'a, V, S>`] from a [`map::IterMut<'a, V>`] unsafely. + /// + /// # Safety + /// + /// `iter_mut` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_iter_mut_unchecked( + iter_mut: map::IterMut<'a, Entity, V>, + ) -> IterMut<'a, V, S> { + IterMut(iter_mut, PhantomData) + } + /// Returns the inner [`IterMut`](map::IterMut). - pub fn into_inner(self) -> map::IterMut<'a, Entity, V> { + pub const fn into_inner(self) -> map::IterMut<'a, Entity, V> { self.0 } @@ -965,7 +1015,8 @@ impl Debug for IterMut<'_, V> { impl Default for IterMut<'_, V> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IterMut` is empty. + unsafe { Self::from_iter_mut_unchecked(Default::default()) } } } @@ -976,6 +1027,18 @@ impl Default for IterMut<'_, V> { pub struct IntoIter(map::IntoIter, PhantomData); impl IntoIter { + /// Constructs a [`IntoIter`] from a [`map::IntoIter`] unsafely. + /// + /// # Safety + /// + /// `into_iter` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_into_iter_unchecked( + into_iter: map::IntoIter, + ) -> IntoIter { + IntoIter(into_iter, PhantomData) + } + /// Returns the inner [`IntoIter`](map::IntoIter). pub fn into_inner(self) -> map::IntoIter { self.0 @@ -1030,7 +1093,8 @@ impl FusedIterator for IntoIter {} impl Clone for IntoIter { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `IntoIter`. + unsafe { Self::from_into_iter_unchecked(self.0.clone()) } } } @@ -1045,7 +1109,8 @@ impl Debug for IntoIter { impl Default for IntoIter { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IntoIter` is empty. + unsafe { Self::from_into_iter_unchecked(Default::default()) } } } @@ -1056,14 +1121,26 @@ impl Default for IntoIter { pub struct Drain<'a, V, S = EntityHash>(map::Drain<'a, Entity, V>, PhantomData); impl<'a, V> Drain<'a, V> { - /// Returns the inner [`Drain`](map::Drain). + /// Constructs a [`Drain<'a, V, S>`] from a [`map::Drain<'a, V>`] unsafely. + /// + /// # Safety + /// + /// `drain` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_drain_unchecked( + drain: map::Drain<'a, Entity, V>, + ) -> Drain<'a, V, S> { + Drain(drain, PhantomData) + } + + /// Returns the inner [`Drain`](indexmap::map::Drain). pub fn into_inner(self) -> map::Drain<'a, Entity, V> { self.0 } /// Returns a slice of the remaining entries in the iterator. /// - /// Equivalent to [`map::Drain::as_slice`]. + /// Equivalent to [`map::Drain::as_slice`](`indexmap::map::Drain::as_slice`). pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } @@ -1116,8 +1193,18 @@ impl Debug for Drain<'_, V> { pub struct Keys<'a, V, S = EntityHash>(map::Keys<'a, Entity, V>, PhantomData); impl<'a, V> Keys<'a, V> { + /// Constructs a [`Keys<'a, V, S>`] from a [`map::Keys<'a, V>`] unsafely. + /// + /// # Safety + /// + /// `keys` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_keys_unchecked(keys: map::Keys<'a, Entity, V>) -> Keys<'a, V, S> { + Keys(keys, PhantomData) + } + /// Returns the inner [`Keys`](map::Keys). - pub fn into_inner(self) -> map::Keys<'a, Entity, V> { + pub const fn into_inner(self) -> map::Keys<'a, Entity, V> { self.0 } } @@ -1162,7 +1249,8 @@ impl Index for Keys<'_, V> { impl Clone for Keys<'_, V> { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `Keys`. + unsafe { Self::from_keys_unchecked(self.0.clone()) } } } @@ -1174,7 +1262,8 @@ impl Debug for Keys<'_, V> { impl Default for Keys<'_, V> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `Keys` is empty. + unsafe { Self::from_keys_unchecked(Default::default()) } } } @@ -1188,6 +1277,18 @@ unsafe impl EntitySetIterator for Keys<'_, V> {} pub struct IntoKeys(map::IntoKeys, PhantomData); impl IntoKeys { + /// Constructs a [`IntoKeys`] from a [`map::IntoKeys`] unsafely. + /// + /// # Safety + /// + /// `into_keys` must either be empty, or have been obtained from a + /// [`IndexMap`] using the `S` hasher. + pub const unsafe fn from_into_keys_unchecked( + into_keys: map::IntoKeys, + ) -> IntoKeys { + IntoKeys(into_keys, PhantomData) + } + /// Returns the inner [`IntoKeys`](map::IntoKeys). pub fn into_inner(self) -> map::IntoKeys { self.0 @@ -1235,7 +1336,8 @@ impl Debug for IntoKeys { impl Default for IntoKeys { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IntoKeys` is empty. + unsafe { Self::from_into_keys_unchecked(Default::default()) } } } diff --git a/crates/bevy_ecs/src/entity/index_set.rs b/crates/bevy_ecs/src/entity/index_set.rs index dbb74419c21e2..ff64f26a09b2a 100644 --- a/crates/bevy_ecs/src/entity/index_set.rs +++ b/crates/bevy_ecs/src/entity/index_set.rs @@ -16,7 +16,7 @@ use core::{ ptr, }; -use indexmap::set::{self, IndexSet}; +use indexmap::{self, set, IndexSet}; use super::{Entity, EntityHash, EntitySetIterator}; @@ -29,7 +29,7 @@ use bevy_reflect::Reflect; #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone, Default)] -pub struct EntityIndexSet(pub(crate) IndexSet); +pub struct EntityIndexSet(IndexSet); impl EntityIndexSet { /// Creates an empty `EntityIndexSet`. @@ -50,6 +50,11 @@ impl EntityIndexSet { Self(IndexSet::with_capacity_and_hasher(n, EntityHash)) } + /// Constructs an `EntityIndexSet` from an [`IndexSet`]. + pub const fn from_index_set(set: IndexSet) -> Self { + Self(set) + } + /// Returns the inner [`IndexSet`]. pub fn into_inner(self) -> IndexSet { self.0 @@ -205,6 +210,7 @@ impl Eq for EntityIndexSet {} impl Index<(Bound, Bound)> for EntityIndexSet { type Output = Slice; + fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -213,6 +219,7 @@ impl Index<(Bound, Bound)> for EntityIndexSet { impl Index> for EntityIndexSet { type Output = Slice; + fn index(&self, key: Range) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -221,6 +228,7 @@ impl Index> for EntityIndexSet { impl Index> for EntityIndexSet { type Output = Slice; + fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -229,6 +237,7 @@ impl Index> for EntityIndexSet { impl Index for EntityIndexSet { type Output = Slice; + fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -237,6 +246,7 @@ impl Index for EntityIndexSet { impl Index> for EntityIndexSet { type Output = Slice; + fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -245,6 +255,7 @@ impl Index> for EntityIndexSet { impl Index> for EntityIndexSet { type Output = Slice; + fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -253,6 +264,7 @@ impl Index> for EntityIndexSet { impl Index> for EntityIndexSet { type Output = Slice; + fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } @@ -261,6 +273,7 @@ impl Index> for EntityIndexSet { impl Index for EntityIndexSet { type Output = Entity; + fn index(&self, key: usize) -> &Entity { self.0.index(key) } @@ -328,7 +341,7 @@ impl Slice { clippy::borrowed_box, reason = "We wish to access the Box API of the inner type, without consuming it." )] - pub fn as_boxed_inner(self: &Box) -> &Box> { + pub const fn as_boxed_inner(self: &Box) -> &Box> { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { &*(ptr::from_ref(self).cast::>>()) } } @@ -489,6 +502,7 @@ impl Eq for Slice {} impl Index<(Bound, Bound)> for Slice { type Output = Self; + fn index(&self, key: (Bound, Bound)) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -497,6 +511,7 @@ impl Index<(Bound, Bound)> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: Range) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -505,6 +520,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Slice; + fn index(&self, key: RangeFrom) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -513,6 +529,7 @@ impl Index> for Slice { impl Index for Slice { type Output = Self; + fn index(&self, key: RangeFull) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -521,6 +538,7 @@ impl Index for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -529,6 +547,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeTo) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -537,6 +556,7 @@ impl Index> for Slice { impl Index> for Slice { type Output = Self; + fn index(&self, key: RangeToInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } @@ -545,6 +565,7 @@ impl Index> for Slice { impl Index for Slice { type Output = Entity; + fn index(&self, key: usize) -> &Entity { self.1.index(key) } @@ -558,8 +579,18 @@ impl Index for Slice { pub struct Iter<'a, S = EntityHash>(set::Iter<'a, Entity>, PhantomData); impl<'a> Iter<'a> { + /// Constructs a [`Iter<'a, S>`] from a [`set::Iter<'a>`] unsafely. + /// + /// # Safety + /// + /// `iter` must either be empty, or have been obtained from a + /// [`IndexSet`] using the `S` hasher. + pub const unsafe fn from_iter_unchecked(iter: set::Iter<'a, Entity>) -> Iter<'a, S> { + Iter(iter, PhantomData) + } + /// Returns the inner [`Iter`](set::Iter). - pub fn into_inner(self) -> set::Iter<'a, Entity> { + pub const fn into_inner(self) -> set::Iter<'a, Entity> { self.0 } @@ -604,7 +635,8 @@ impl FusedIterator for Iter<'_> {} impl Clone for Iter<'_> { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `Iter`. + unsafe { Self::from_iter_unchecked(self.0.clone()) } } } @@ -616,7 +648,8 @@ impl Debug for Iter<'_> { impl Default for Iter<'_> { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `Iter` is empty. + unsafe { Self::from_iter_unchecked(Default::default()) } } } @@ -631,6 +664,18 @@ unsafe impl EntitySetIterator for Iter<'_> {} pub struct IntoIter(set::IntoIter, PhantomData); impl IntoIter { + /// Constructs a [`IntoIter`] from a [`set::IntoIter`] unsafely. + /// + /// # Safety + /// + /// `into_iter` must either be empty, or have been obtained from a + /// [`IndexSet`] using the `S` hasher. + pub const unsafe fn from_into_iter_unchecked( + into_iter: set::IntoIter, + ) -> IntoIter { + IntoIter(into_iter, PhantomData) + } + /// Returns the inner [`IntoIter`](set::IntoIter). pub fn into_inner(self) -> set::IntoIter { self.0 @@ -677,7 +722,8 @@ impl FusedIterator for IntoIter {} impl Clone for IntoIter { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + // SAFETY: We are cloning an already valid `IntoIter`. + unsafe { Self::from_into_iter_unchecked(self.0.clone()) } } } @@ -692,7 +738,8 @@ impl Debug for IntoIter { impl Default for IntoIter { fn default() -> Self { - Self(Default::default(), PhantomData) + // SAFETY: `IntoIter` is empty. + unsafe { Self::from_into_iter_unchecked(Default::default()) } } } @@ -707,6 +754,16 @@ unsafe impl EntitySetIterator for IntoIter {} pub struct Drain<'a, S = EntityHash>(set::Drain<'a, Entity>, PhantomData); impl<'a> Drain<'a> { + /// Constructs a [`Drain<'a, S>`] from a [`set::Drain<'a>`] unsafely. + /// + /// # Safety + /// + /// `drain` must either be empty, or have been obtained from a + /// [`IndexSet`] using the `S` hasher. + pub const unsafe fn from_drain_unchecked(drain: set::Drain<'a, Entity>) -> Drain<'a, S> { + Drain(drain, PhantomData) + } + /// Returns the inner [`Drain`](set::Drain). pub fn into_inner(self) -> set::Drain<'a, Entity> { self.0 diff --git a/crates/bevy_ecs/src/entity/unique_array.rs b/crates/bevy_ecs/src/entity/unique_array.rs index db6b67bd7af95..6e3ae3208a82b 100644 --- a/crates/bevy_ecs/src/entity/unique_array.rs +++ b/crates/bevy_ecs/src/entity/unique_array.rs @@ -31,6 +31,7 @@ use super::{ /// and some [`TryFrom`] implementations. /// /// When `T` is [`Entity`], use [`UniqueEntityArray`]. +#[repr(transparent)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct UniqueEntityEquivalentArray([T; N]); @@ -113,7 +114,7 @@ impl UniqueEntityEquivalentArray { } /// Returns a reference to the inner array. - pub fn as_inner(&self) -> &[T; N] { + pub const fn as_inner(&self) -> &[T; N] { &self.0 } @@ -125,7 +126,7 @@ impl UniqueEntityEquivalentArray { /// Returns a mutable slice containing the entire array. Equivalent to /// `&mut s[..]`. - pub fn as_mut_slice(&mut self) -> &mut UniqueEntityEquivalentSlice { + pub const fn as_mut_slice(&mut self) -> &mut UniqueEntityEquivalentSlice { // SAFETY: All elements in the original array are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(self.0.as_mut_slice()) } } @@ -143,21 +144,20 @@ impl Deref for UniqueEntityEquivalentArray< type Target = UniqueEntityEquivalentSlice; fn deref(&self) -> &Self::Target { - // SAFETY: All elements in the original array are unique. - unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(&self.0) } + self.as_slice() } } impl DerefMut for UniqueEntityEquivalentArray { fn deref_mut(&mut self) -> &mut Self::Target { - // SAFETY: All elements in the original array are unique. - unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(&mut self.0) } + self.as_mut_slice() } } impl Default for UniqueEntityEquivalentArray { fn default() -> Self { - Self([]) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_array_unchecked([]) } } } @@ -170,7 +170,7 @@ impl<'a, T: EntityEquivalent, const N: usize> IntoIterator fn into_iter(self) -> Self::IntoIter { // SAFETY: All elements in the original array are unique. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.iter()) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.iter()) } } } @@ -181,7 +181,7 @@ impl IntoIterator for UniqueEntityEquivalen fn into_iter(self) -> Self::IntoIter { // SAFETY: All elements in the original array are unique. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.into_iter()) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.into_iter()) } } } @@ -221,6 +221,7 @@ impl Index<(Bound, Bound)> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -231,6 +232,7 @@ impl Index> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: Range) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -241,6 +243,7 @@ impl Index> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -249,6 +252,7 @@ impl Index> impl Index for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -259,6 +263,7 @@ impl Index> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -269,6 +274,7 @@ impl Index> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -279,6 +285,7 @@ impl Index> for UniqueEntityEquivalentArray { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -287,6 +294,7 @@ impl Index> impl Index for UniqueEntityEquivalentArray { type Output = T; + fn index(&self, key: usize) -> &T { self.0.index(key) } @@ -357,37 +365,43 @@ impl IndexMut> impl From<&[T; 1]> for UniqueEntityEquivalentArray { fn from(value: &[T; 1]) -> Self { - Self(value.clone()) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_array_unchecked(value.clone()) } } } impl From<&[T; 0]> for UniqueEntityEquivalentArray { fn from(value: &[T; 0]) -> Self { - Self(value.clone()) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_array_unchecked(value.clone()) } } } impl From<&mut [T; 1]> for UniqueEntityEquivalentArray { fn from(value: &mut [T; 1]) -> Self { - Self(value.clone()) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_array_unchecked(value.clone()) } } } impl From<&mut [T; 0]> for UniqueEntityEquivalentArray { fn from(value: &mut [T; 0]) -> Self { - Self(value.clone()) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_array_unchecked(value.clone()) } } } impl From<[T; 1]> for UniqueEntityEquivalentArray { fn from(value: [T; 1]) -> Self { - Self(value) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_array_unchecked(value) } } } impl From<[T; 0]> for UniqueEntityEquivalentArray { fn from(value: [T; 0]) -> Self { - Self(value) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_array_unchecked(value) } } } diff --git a/crates/bevy_ecs/src/entity/unique_slice.rs b/crates/bevy_ecs/src/entity/unique_slice.rs index 26ebe8674f498..c871ddbf2a85d 100644 --- a/crates/bevy_ecs/src/entity/unique_slice.rs +++ b/crates/bevy_ecs/src/entity/unique_slice.rs @@ -227,7 +227,7 @@ impl UniqueEntityEquivalentSlice { /// /// Note that `UniqueEntityEquivalentSlice::get_mut` cannot be called with a [`usize`]. /// - /// [`[T]::get_mut`]: `slice::get_mut`s + /// [`[T]::get_mut`]: `slice::get_mut` pub fn get_mut(&mut self, index: I) -> Option<&mut Self> where Self: Index, @@ -300,7 +300,7 @@ impl UniqueEntityEquivalentSlice { /// Returns an iterator over the slice. pub fn iter(&self) -> Iter<'_, T> { // SAFETY: All elements in the original slice are unique. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.iter()) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.iter()) } } /// Returns an iterator over all contiguous windows of length @@ -311,9 +311,7 @@ impl UniqueEntityEquivalentSlice { /// [`[T]::windows`]: `slice::windows` pub fn windows(&self, size: usize) -> Windows<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. - unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.windows(size)) - } + unsafe { UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.windows(size)) } } /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the @@ -325,9 +323,7 @@ impl UniqueEntityEquivalentSlice { pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked( - self.0.chunks(chunk_size), - ) + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.chunks(chunk_size)) } } @@ -340,13 +336,14 @@ impl UniqueEntityEquivalentSlice { pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.chunks_mut(chunk_size), ) } } - /// + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// beginning of the slice. /// /// Equivalent to [`[T]::chunks_exact`]. /// @@ -354,7 +351,7 @@ impl UniqueEntityEquivalentSlice { pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked( self.0.chunks_exact(chunk_size), ) } @@ -369,7 +366,7 @@ impl UniqueEntityEquivalentSlice { pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.chunks_exact_mut(chunk_size), ) } @@ -384,9 +381,7 @@ impl UniqueEntityEquivalentSlice { pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked( - self.0.rchunks(chunk_size), - ) + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.rchunks(chunk_size)) } } @@ -399,7 +394,7 @@ impl UniqueEntityEquivalentSlice { pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.rchunks_mut(chunk_size), ) } @@ -414,7 +409,7 @@ impl UniqueEntityEquivalentSlice { pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked( self.0.rchunks_exact(chunk_size), ) } @@ -429,7 +424,7 @@ impl UniqueEntityEquivalentSlice { pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.rchunks_exact_mut(chunk_size), ) } @@ -446,9 +441,7 @@ impl UniqueEntityEquivalentSlice { F: FnMut(&T, &T) -> bool, { // SAFETY: Any subslice of a unique slice is also unique. - unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.chunk_by(pred)) - } + unsafe { UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.chunk_by(pred)) } } /// Returns an iterator over the slice producing non-overlapping mutable @@ -463,7 +456,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.chunk_by_mut(pred), ) } @@ -584,9 +577,7 @@ impl UniqueEntityEquivalentSlice { F: FnMut(&T) -> bool, { // SAFETY: Any subslice of a unique slice is also unique. - unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.split(pred)) - } + unsafe { UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.split(pred)) } } /// Returns an iterator over mutable subslices separated by elements that @@ -601,7 +592,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.split_mut(pred), ) } @@ -619,9 +610,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked( - self.0.split_inclusive(pred), - ) + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.split_inclusive(pred)) } } @@ -637,7 +626,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.split_inclusive_mut(pred), ) } @@ -654,9 +643,7 @@ impl UniqueEntityEquivalentSlice { F: FnMut(&T) -> bool, { // SAFETY: Any subslice of a unique slice is also unique. - unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.rsplit(pred)) - } + unsafe { UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.rsplit(pred)) } } /// Returns an iterator over mutable subslices separated by elements that @@ -672,7 +659,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.rsplit_mut(pred), ) } @@ -690,7 +677,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.splitn(n, pred)) + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.splitn(n, pred)) } } @@ -706,7 +693,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.splitn_mut(n, pred), ) } @@ -724,7 +711,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIter::from_slice_iterator_unchecked(self.0.rsplitn(n, pred)) + UniqueEntityEquivalentSliceIter::from_slice_iter_unchecked(self.0.rsplitn(n, pred)) } } @@ -740,7 +727,7 @@ impl UniqueEntityEquivalentSlice { { // SAFETY: Any subslice of a unique slice is also unique. unsafe { - UniqueEntityEquivalentSliceIterMut::from_mut_slice_iterator_unchecked( + UniqueEntityEquivalentSliceIterMut::from_mut_slice_iter_unchecked( self.0.rsplitn_mut(n, pred), ) } @@ -1360,6 +1347,7 @@ impl TryFrom<&mut UniqueEntityEquiva impl Index<(Bound, Bound)> for UniqueEntityEquivalentSlice { type Output = Self; + fn index(&self, key: (Bound, Bound)) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1368,6 +1356,7 @@ impl Index<(Bound, Bound)> for UniqueEntityEq impl Index> for UniqueEntityEquivalentSlice { type Output = Self; + fn index(&self, key: Range) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1376,6 +1365,7 @@ impl Index> for UniqueEntityEquivalentSlice impl Index> for UniqueEntityEquivalentSlice { type Output = Self; + fn index(&self, key: RangeFrom) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1384,6 +1374,7 @@ impl Index> for UniqueEntityEquivalentSlic impl Index for UniqueEntityEquivalentSlice { type Output = Self; + fn index(&self, key: RangeFull) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1392,6 +1383,7 @@ impl Index for UniqueEntityEquivalentSlice { impl Index> for UniqueEntityEquivalentSlice { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeInclusive) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1400,6 +1392,7 @@ impl Index> for UniqueEntityEquivalen impl Index> for UniqueEntityEquivalentSlice { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeTo) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1408,6 +1401,7 @@ impl Index> for UniqueEntityEquivalentSlice< impl Index> for UniqueEntityEquivalentSlice { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeToInclusive) -> &Self { // SAFETY: All elements in the original slice are unique. unsafe { Self::from_slice_unchecked(self.0.index(key)) } @@ -1516,13 +1510,14 @@ impl<'a, T: EntityEquivalent> UniqueEntityIter> { /// An iterator that yields `&UniqueEntityEquivalentSlice`. Note that an entity may appear /// in multiple slices, depending on the wrapped iterator. +#[repr(transparent)] #[derive(Debug)] pub struct UniqueEntityEquivalentSliceIter< 'a, T: EntityEquivalent + 'a, I: Iterator, > { - pub(crate) iter: I, + iter: I, } impl<'a, T: EntityEquivalent + 'a, I: Iterator> @@ -1533,7 +1528,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> /// # Safety /// /// All elements in each of the slices must be unique. - pub unsafe fn from_slice_iterator_unchecked(iter: I) -> Self { + pub const unsafe fn from_slice_iter_unchecked(iter: I) -> Self { Self { iter } } @@ -1543,7 +1538,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> } /// Returns a reference to the inner `I`. - pub fn as_inner(&self) -> &I { + pub const fn as_inner(&self) -> &I { &self.iter } @@ -1553,7 +1548,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> /// /// `self` must always contain an iterator that yields unique elements, /// even while this reference is live. - pub unsafe fn as_mut_inner(&mut self) -> &mut I { + pub const unsafe fn as_mut_inner(&mut self) -> &mut I { &mut self.iter } } @@ -1699,13 +1694,14 @@ pub type RSplitN<'a, P, T = Entity> = /// An iterator that yields `&mut UniqueEntityEquivalentSlice`. Note that an entity may appear /// in multiple slices, depending on the wrapped iterator. +#[repr(transparent)] #[derive(Debug)] pub struct UniqueEntityEquivalentSliceIterMut< 'a, T: EntityEquivalent + 'a, I: Iterator, > { - pub(crate) iter: I, + iter: I, } impl<'a, T: EntityEquivalent + 'a, I: Iterator> @@ -1716,7 +1712,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> /// # Safety /// /// All elements in each of the slices must be unique. - pub unsafe fn from_mut_slice_iterator_unchecked(iter: I) -> Self { + pub const unsafe fn from_mut_slice_iter_unchecked(iter: I) -> Self { Self { iter } } @@ -1726,7 +1722,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> } /// Returns a reference to the inner `I`. - pub fn as_inner(&self) -> &I { + pub const fn as_inner(&self) -> &I { &self.iter } @@ -1736,7 +1732,7 @@ impl<'a, T: EntityEquivalent + 'a, I: Iterator> /// /// `self` must always contain an iterator that yields unique elements, /// even while this reference is live. - pub unsafe fn as_mut_inner(&mut self) -> &mut I { + pub const unsafe fn as_mut_inner(&mut self) -> &mut I { &mut self.iter } } diff --git a/crates/bevy_ecs/src/entity/unique_vec.rs b/crates/bevy_ecs/src/entity/unique_vec.rs index 30f9984e70be7..22b2ad67eb909 100644 --- a/crates/bevy_ecs/src/entity/unique_vec.rs +++ b/crates/bevy_ecs/src/entity/unique_vec.rs @@ -7,6 +7,7 @@ use core::{ Bound, Deref, DerefMut, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }, + ptr, }; use alloc::{ @@ -37,6 +38,7 @@ use super::{ /// and not recommended. /// /// When `T` is [`Entity`], use the [`UniqueEntityVec`] alias. +#[repr(transparent)] #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct UniqueEntityEquivalentVec(Vec); @@ -50,14 +52,16 @@ impl UniqueEntityEquivalentVec { /// /// Equivalent to [`Vec::new`]. pub const fn new() -> Self { - Self(Vec::new()) + // SAFETY: Any empty Vec cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::new()) } } /// Constructs a new, empty `UniqueEntityEquivalentVec` with at least the specified capacity. /// - /// Equivalent to [`Vec::with_capacity`] + /// Equivalent to [`Vec::with_capacity`]. pub fn with_capacity(capacity: usize) -> Self { - Self(Vec::with_capacity(capacity)) + // SAFETY: Any empty Vec cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::with_capacity(capacity)) } } /// Creates a `UniqueEntityEquivalentVec` directly from a pointer, a length, and a capacity. @@ -69,8 +73,9 @@ impl UniqueEntityEquivalentVec { /// It must be safe to call [`Vec::from_raw_parts`] with these inputs, /// and the resulting [`Vec`] must only contain unique elements. pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { - // SAFETY: Caller ensures it's safe to call `Vec::from_raw_parts` - Self(unsafe { Vec::from_raw_parts(ptr, length, capacity) }) + // SAFETY: Caller ensures it is safe to call `Vec::from_raw_parts`, and that + // the resulting `Vec` only contains unique elements. + unsafe { Self::from_vec_unchecked(Vec::from_raw_parts(ptr, length, capacity)) } } /// Constructs a `UniqueEntityEquivalentVec` from a [`Vec`] unsafely. @@ -78,17 +83,37 @@ impl UniqueEntityEquivalentVec { /// # Safety /// /// `vec` must contain only unique elements. - pub unsafe fn from_vec_unchecked(vec: Vec) -> Self { + pub const unsafe fn from_vec_unchecked(vec: Vec) -> Self { Self(vec) } + /// Constructs a `UniqueEntityEquivalentVec` from a [`&Vec`](Vec) unsafely. + /// + /// # Safety + /// + /// `vec` must contain only unique elements. + pub const unsafe fn from_vec_ref_unchecked(vec: &Vec) -> &Self { + // SAFETY: UniqueEntityEquivalentVec is a transparent wrapper around Vec. + unsafe { &*ptr::from_ref(vec).cast() } + } + + /// Constructs a `UniqueEntityEquivalentVec` from a [`&mut Vec`](Vec) unsafely. + /// + /// # Safety + /// + /// `vec` must contain only unique elements. + pub const unsafe fn from_vec_mut_unchecked(vec: &mut Vec) -> &mut Self { + // SAFETY: UniqueEntityEquivalentVec is a transparent wrapper around Vec. + unsafe { &mut *ptr::from_mut(vec).cast() } + } + /// Returns the inner [`Vec`]. pub fn into_inner(self) -> Vec { self.0 } /// Returns a reference to the inner [`Vec`]. - pub fn as_vec(&self) -> &Vec { + pub const fn as_vec(&self) -> &Vec { &self.0 } @@ -98,7 +123,7 @@ impl UniqueEntityEquivalentVec { /// /// The elements of this `Vec` must always remain unique, even while /// this mutable reference is live. - pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { &mut self.0 } @@ -106,7 +131,7 @@ impl UniqueEntityEquivalentVec { /// reallocating. /// /// Equivalent to [`Vec::capacity`]. - pub fn capacity(&self) -> usize { + pub const fn capacity(&self) -> usize { self.0.capacity() } @@ -165,13 +190,15 @@ impl UniqueEntityEquivalentVec { } /// Extracts a slice containing the entire vector. - pub fn as_slice(&self) -> &UniqueEntityEquivalentSlice { - self + pub const fn as_slice(&self) -> &UniqueEntityEquivalentSlice { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.as_slice()) } } /// Extracts a mutable slice of the entire vector. - pub fn as_mut_slice(&mut self) -> &mut UniqueEntityEquivalentSlice { - self + pub const fn as_mut_slice(&mut self) -> &mut UniqueEntityEquivalentSlice { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(self.0.as_mut_slice()) } } /// Shortens the vector, keeping the first `len` elements and dropping @@ -186,14 +213,14 @@ impl UniqueEntityEquivalentVec { /// valid for zero sized reads if the vector didn't allocate. /// /// Equivalent to [`Vec::as_ptr`]. - pub fn as_ptr(&self) -> *const T { + pub const fn as_ptr(&self) -> *const T { self.0.as_ptr() } /// Returns a raw mutable pointer to the vector's buffer, or a dangling /// raw pointer valid for zero sized reads if the vector didn't allocate. /// /// Equivalent to [`Vec::as_mut_ptr`]. - pub fn as_mut_ptr(&mut self) -> *mut T { + pub const fn as_mut_ptr(&mut self) -> *mut T { self.0.as_mut_ptr() } @@ -331,7 +358,7 @@ impl UniqueEntityEquivalentVec { R: RangeBounds, { // SAFETY: `self` and thus `range` contains only unique elements. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.drain(range)) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.drain(range)) } } /// Clears the vector, removing all values. @@ -345,14 +372,14 @@ impl UniqueEntityEquivalentVec { /// as its 'length'. /// /// Equivalent to [`Vec::len`]. - pub fn len(&self) -> usize { + pub const fn len(&self) -> usize { self.0.len() } /// Returns `true` if the vector contains no elements. /// /// Equivalent to [`Vec::is_empty`]. - pub fn is_empty(&self) -> bool { + pub const fn is_empty(&self) -> bool { self.0.is_empty() } @@ -360,7 +387,8 @@ impl UniqueEntityEquivalentVec { /// /// Equivalent to [`Vec::split_off`]. pub fn split_off(&mut self, at: usize) -> Self { - Self(self.0.split_off(at)) + // SAFETY: Any subslice/subsection of a `UniqueEntityVec` is also unique. + unsafe { Self::from_vec_unchecked(self.0.split_off(at)) } } /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. @@ -410,13 +438,14 @@ impl UniqueEntityEquivalentVec { I: EntitySet, { // SAFETY: `self` and thus `range` contains only unique elements. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.splice(range, replace_with)) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.splice(range, replace_with)) } } } impl Default for UniqueEntityEquivalentVec { fn default() -> Self { - Self(Vec::default()) + // SAFETY: An empty `Vec` cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::default()) } } } @@ -424,15 +453,13 @@ impl Deref for UniqueEntityEquivalentVec { type Target = UniqueEntityEquivalentSlice; fn deref(&self) -> &Self::Target { - // SAFETY: All elements in the original slice are unique. - unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(&self.0) } + self.as_slice() } } impl DerefMut for UniqueEntityEquivalentVec { fn deref_mut(&mut self) -> &mut Self::Target { - // SAFETY: All elements in the original slice are unique. - unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(&mut self.0) } + self.as_mut_slice() } } @@ -446,7 +473,7 @@ where fn into_iter(self) -> Self::IntoIter { // SAFETY: `self` contains only unique elements. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.iter()) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.iter()) } } } @@ -457,7 +484,7 @@ impl IntoIterator for UniqueEntityEquivalentVec { fn into_iter(self) -> Self::IntoIter { // SAFETY: `self` contains only unique elements. - unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.into_iter()) } + unsafe { UniqueEntityIter::from_iter_unchecked(self.0.into_iter()) } } } @@ -695,37 +722,43 @@ where impl From<&[T; 1]> for UniqueEntityEquivalentVec { fn from(value: &[T; 1]) -> Self { - Self(Vec::from(value)) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } impl From<&[T; 0]> for UniqueEntityEquivalentVec { fn from(value: &[T; 0]) -> Self { - Self(Vec::from(value)) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } impl From<&mut [T; 1]> for UniqueEntityEquivalentVec { fn from(value: &mut [T; 1]) -> Self { - Self(Vec::from(value)) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } impl From<&mut [T; 0]> for UniqueEntityEquivalentVec { fn from(value: &mut [T; 0]) -> Self { - Self(Vec::from(value)) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } impl From<[T; 1]> for UniqueEntityEquivalentVec { fn from(value: [T; 1]) -> Self { - Self(Vec::from(value)) + // SAFETY: An array with 1 element cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } impl From<[T; 0]> for UniqueEntityEquivalentVec { fn from(value: [T; 0]) -> Self { - Self(Vec::from(value)) + // SAFETY: An empty array cannot contain duplicates. + unsafe { Self::from_vec_unchecked(Vec::from(value)) } } } @@ -733,7 +766,8 @@ impl From<&UniqueEntityEquivalentAr for UniqueEntityEquivalentVec { fn from(value: &UniqueEntityEquivalentArray) -> Self { - Self(Vec::from(value.as_inner().clone())) + // SAFETY: `UniqueEntityEquivalentArray` only contains unique elements. + unsafe { Self::from_vec_unchecked(Vec::from(value.as_inner().clone())) } } } @@ -741,7 +775,8 @@ impl From<&mut UniqueEntityEquivale for UniqueEntityEquivalentVec { fn from(value: &mut UniqueEntityEquivalentArray) -> Self { - Self(Vec::from(value.as_inner().clone())) + // SAFETY: `UniqueEntityEquivalentArray` only contains unique elements. + unsafe { Self::from_vec_unchecked(Vec::from(value.as_inner().clone())) } } } @@ -749,7 +784,8 @@ impl From for UniqueEntityEquivalentVec { fn from(value: UniqueEntityEquivalentArray) -> Self { - Self(Vec::from(value.into_inner())) + // SAFETY: `UniqueEntityEquivalentArray` only contains unique elements. + unsafe { Self::from_vec_unchecked(Vec::from(value.into_inner())) } } } @@ -867,7 +903,8 @@ impl TryFrom> impl From> for UniqueEntityEquivalentVec { fn from(value: BTreeSet) -> Self { - Self(value.into_iter().collect::>()) + // SAFETY: A `BTreeSet` over an `EntityEquivalent` T only contains unique elements. + unsafe { Self::from_vec_unchecked(value.into_iter().collect::>()) } } } @@ -953,6 +990,7 @@ impl<'a, T: EntityEquivalent + Copy + 'a> Extend<&'a T> for UniqueEntityEquivale impl Index<(Bound, Bound)> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -961,6 +999,7 @@ impl Index<(Bound, Bound)> for UniqueEntityEq impl Index> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: Range) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -969,6 +1008,7 @@ impl Index> for UniqueEntityEquivalentVec { impl Index> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -977,6 +1017,7 @@ impl Index> for UniqueEntityEquivalentVec< impl Index for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -985,6 +1026,7 @@ impl Index for UniqueEntityEquivalentVec { impl Index> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -993,6 +1035,7 @@ impl Index> for UniqueEntityEquivalen impl Index> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -1001,6 +1044,7 @@ impl Index> for UniqueEntityEquivalentVec impl Index> for UniqueEntityEquivalentVec { type Output = UniqueEntityEquivalentSlice; + fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: All elements in the original slice are unique. unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.0.index(key)) } @@ -1009,6 +1053,7 @@ impl Index> for UniqueEntityEquival impl Index for UniqueEntityEquivalentVec { type Output = T; + fn index(&self, key: usize) -> &T { self.0.index(key) } diff --git a/crates/bevy_ecs/src/error/bevy_error.rs b/crates/bevy_ecs/src/error/bevy_error.rs index ff0b884205f98..15e77b022d535 100644 --- a/crates/bevy_ecs/src/error/bevy_error.rs +++ b/crates/bevy_ecs/src/error/bevy_error.rs @@ -487,6 +487,7 @@ mod tests { { skip = true; } + if skip { lines.next().unwrap(); } diff --git a/crates/bevy_ecs/src/relationship/relationship_source_collection.rs b/crates/bevy_ecs/src/relationship/relationship_source_collection.rs index f0e23c0573248..c8d8315ff3d5b 100644 --- a/crates/bevy_ecs/src/relationship/relationship_source_collection.rs +++ b/crates/bevy_ecs/src/relationship/relationship_source_collection.rs @@ -244,7 +244,7 @@ impl RelationshipSourceCollection for EntityHashSet { } fn reserve(&mut self, additional: usize) { - self.0.reserve(additional); + self.deref_mut().reserve(additional); } fn with_capacity(capacity: usize) -> Self { @@ -256,9 +256,7 @@ impl RelationshipSourceCollection for EntityHashSet { } fn remove(&mut self, entity: Entity) -> bool { - // We need to call the remove method on the underlying hash set, - // which takes its argument by reference - self.0.remove(&entity) + self.deref_mut().remove(&entity) } fn iter(&self) -> Self::SourceIter<'_> { @@ -266,15 +264,15 @@ impl RelationshipSourceCollection for EntityHashSet { } fn len(&self) -> usize { - self.len() + self.deref().len() } fn clear(&mut self) { - self.0.clear(); + self.deref_mut().clear(); } fn shrink_to_fit(&mut self) { - self.0.shrink_to_fit(); + self.deref_mut().shrink_to_fit(); } fn extend_from_iter(&mut self, entities: impl IntoIterator) { diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index eff324be204d3..93e9a8df3ebab 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -994,7 +994,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// fn into_iter(self) -> Self::IntoIter { /// // SAFETY: `Friends` ensures that it unique_list contains only unique entities. - /// unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) } + /// unsafe { UniqueEntityIter::from_iter_unchecked(self.unique_list.iter()) } /// } /// } /// @@ -1049,7 +1049,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// fn into_iter(self) -> Self::IntoIter { /// // SAFETY: `Friends` ensures that it unique_list contains only unique entities. - /// unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) } + /// unsafe { UniqueEntityIter::from_iter_unchecked(self.unique_list.iter()) } /// } /// } /// @@ -1108,7 +1108,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// fn into_iter(self) -> Self::IntoIter { /// // SAFETY: `Friends` ensures that it unique_list contains only unique entities. - /// unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) } + /// unsafe { UniqueEntityIter::from_iter_unchecked(self.unique_list.iter()) } /// } /// } /// diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index 2967681a01b2a..6ec5befd49f62 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -488,7 +488,7 @@ mod parallel { // TODO: this implementation could be used in no_std if there are equivalents of these. use crate::systems::StaticTransformOptimizations; use alloc::{sync::Arc, vec::Vec}; - use bevy_ecs::{entity::UniqueEntityIter, prelude::*, system::lifetimeless::Read}; + use bevy_ecs::{entity::UniqueEntitySlice, prelude::*, system::lifetimeless::Read}; use bevy_tasks::{ComputeTaskPool, TaskPool}; use bevy_utils::Parallel; use core::sync::atomic::{AtomicI32, Ordering}; @@ -698,9 +698,7 @@ mod parallel { // visiting disjoint entities in parallel, which is safe. #[expect(unsafe_code, reason = "Mutating disjoint entities in parallel")] let children_iter = unsafe { - nodes.iter_many_unique_unsafe(UniqueEntityIter::from_iterator_unchecked( - p_children.iter(), - )) + nodes.iter_many_unique_unsafe(UniqueEntitySlice::from_slice_unchecked(p_children)) }; let mut last_child = None;