mirror of
https://github.com/bevyengine/bevy
synced 2024-12-23 19:43:07 +00:00
d38a8dfdd7
# Objective `SAFETY` comments are meant to be placed before `unsafe` blocks and should contain the reasoning of why in this case the usage of unsafe is okay. This is useful when reading the code because it makes it clear which assumptions are required for safety, and makes it easier to spot possible unsoundness holes. It also forces the code writer to think of something to write and maybe look at the safety contracts of any called unsafe methods again to double-check their correct usage. There's a clippy lint called `undocumented_unsafe_blocks` which warns when using a block without such a comment. ## Solution - since clippy expects `SAFETY` instead of `SAFE`, rename those - add `SAFETY` comments in more places - for the last remaining 3 places, add an `#[allow()]` and `// TODO` since I wasn't comfortable enough with the code to justify their safety - add ` #![warn(clippy::undocumented_unsafe_blocks)]` to `bevy_ecs` ### Note for reviewers The first commit only renames `SAFETY` to `SAFE` so it doesn't need a thorough review.cb042a416e..55cef2d6fa
is the diff for all other changes. ### Safety comments where I'm not too familiar with the code774012ece5/crates/bevy_ecs/src/entity/mod.rs (L540-L546)
774012ece5/crates/bevy_ecs/src/world/entity_ref.rs (L249-L252)
### Locations left undocumented with a `TODO` comment5dde944a30/crates/bevy_ecs/src/schedule/executor_parallel.rs (L196-L199)
5dde944a30/crates/bevy_ecs/src/world/entity_ref.rs (L287-L289)
5dde944a30/crates/bevy_ecs/src/world/entity_ref.rs (L413-L415)
Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
94 lines
2 KiB
Rust
94 lines
2 KiB
Rust
use crate::{
|
|
bundle::{Bundle, BundleSpawner},
|
|
entity::Entity,
|
|
world::World,
|
|
};
|
|
use std::iter::FusedIterator;
|
|
|
|
pub struct SpawnBatchIter<'w, I>
|
|
where
|
|
I: Iterator,
|
|
I::Item: Bundle,
|
|
{
|
|
inner: I,
|
|
spawner: BundleSpawner<'w, 'w>,
|
|
}
|
|
|
|
impl<'w, I> SpawnBatchIter<'w, I>
|
|
where
|
|
I: Iterator,
|
|
I::Item: Bundle,
|
|
{
|
|
#[inline]
|
|
pub(crate) fn new(world: &'w mut World, iter: I) -> Self {
|
|
// Ensure all entity allocations are accounted for so `self.entities` can realloc if
|
|
// necessary
|
|
world.flush();
|
|
|
|
let (lower, upper) = iter.size_hint();
|
|
let length = upper.unwrap_or(lower);
|
|
|
|
let bundle_info = world
|
|
.bundles
|
|
.init_info::<I::Item>(&mut world.components, &mut world.storages);
|
|
world.entities.reserve(length as u32);
|
|
let mut spawner = bundle_info.get_bundle_spawner(
|
|
&mut world.entities,
|
|
&mut world.archetypes,
|
|
&mut world.components,
|
|
&mut world.storages,
|
|
*world.change_tick.get_mut(),
|
|
);
|
|
spawner.reserve_storage(length);
|
|
|
|
Self {
|
|
inner: iter,
|
|
spawner,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<I> Drop for SpawnBatchIter<'_, I>
|
|
where
|
|
I: Iterator,
|
|
I::Item: Bundle,
|
|
{
|
|
fn drop(&mut self) {
|
|
for _ in self {}
|
|
}
|
|
}
|
|
|
|
impl<I> Iterator for SpawnBatchIter<'_, I>
|
|
where
|
|
I: Iterator,
|
|
I::Item: Bundle,
|
|
{
|
|
type Item = Entity;
|
|
|
|
fn next(&mut self) -> Option<Entity> {
|
|
let bundle = self.inner.next()?;
|
|
// SAFETY: bundle matches spawner type
|
|
unsafe { Some(self.spawner.spawn(bundle)) }
|
|
}
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
self.inner.size_hint()
|
|
}
|
|
}
|
|
|
|
impl<I, T> ExactSizeIterator for SpawnBatchIter<'_, I>
|
|
where
|
|
I: ExactSizeIterator<Item = T>,
|
|
T: Bundle,
|
|
{
|
|
fn len(&self) -> usize {
|
|
self.inner.len()
|
|
}
|
|
}
|
|
|
|
impl<I, T> FusedIterator for SpawnBatchIter<'_, I>
|
|
where
|
|
I: FusedIterator<Item = T>,
|
|
T: Bundle,
|
|
{
|
|
}
|