Skip to content

Commit 15d35c6

Browse files
committed
Update docs and safety invariants
1 parent b3ec59e commit 15d35c6

File tree

3 files changed

+49
-47
lines changed

3 files changed

+49
-47
lines changed

crates/bevy_ecs/macros/src/fetch.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,7 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
267267
#(#ignored_field_idents: #ignored_field_types,)*
268268
}
269269

270-
// SAFETY: `update_component_access` and `update_archetype_component_access` are called for each item in the struct
271-
unsafe impl #user_impl_generics #path::query::FetchState for #state_struct_name #user_ty_generics #user_where_clauses {
270+
impl #user_impl_generics #path::query::FetchState for #state_struct_name #user_ty_generics #user_where_clauses {
272271
fn init(world: &mut #path::world::World) -> Self {
273272
#state_struct_name {
274273
#(#field_idents: <<#field_types as #path::query::WorldQuery>::State as #path::query::FetchState>::init(world),)*
@@ -304,7 +303,8 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
304303
#(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)*
305304
}
306305

307-
impl #user_impl_generics #path::query::WorldQuery for #read_only_struct_name #user_ty_generics #user_where_clauses {
306+
// SAFETY: `update_component_access` and `update_archetype_component_access` are called on every field
307+
unsafe impl #user_impl_generics #path::query::WorldQuery for #read_only_struct_name #user_ty_generics #user_where_clauses {
308308
type ReadOnly = Self;
309309
type State = #state_struct_name #user_ty_generics;
310310

@@ -372,7 +372,8 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
372372

373373
#read_only_world_query_impl
374374

375-
impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses {
375+
// SAFETY: `update_component_access` and `update_archetype_component_access` are called on every field
376+
unsafe impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses {
376377
type ReadOnly = #read_only_struct_name #user_ty_generics;
377378
type State = #state_struct_name #user_ty_generics;
378379
fn shrink<'__wlong: '__wshort, '__wshort>(item: #path::query::#item_type_alias<'__wlong, Self>)

crates/bevy_ecs/src/query/fetch.rs

+32-31
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,13 @@ use std::{cell::UnsafeCell, marker::PhantomData};
292292
///
293293
/// # bevy_ecs::system::assert_is_system(my_system);
294294
/// ```
295-
pub trait WorldQuery: for<'w> WorldQueryGats<'w, _State = Self::State> {
295+
/// # Safety
296+
///
297+
/// Implementor must ensure that [`WorldQuery::update_component_access`] and
298+
/// [`WorldQuery::update_archetype_component_access`] exactly reflects the results of
299+
/// [`FetchState::matches_archetype`], [`FetchState::matches_table`], [`Fetch::archetype_fetch`], and
300+
/// [`Fetch::table_fetch`].
301+
pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w, _State = Self::State> {
296302
type ReadOnly: ReadOnlyWorldQuery<State = Self::State>;
297303
type State: FetchState;
298304

@@ -429,20 +435,14 @@ pub trait Fetch<'world>: Sized {
429435
/// State used to construct a Fetch. This will be cached inside [`QueryState`](crate::query::QueryState),
430436
/// so it is best to move as much data / computation here as possible to reduce the cost of
431437
/// constructing Fetch.
432-
///
433-
/// # Safety
434-
///
435-
/// Implementor must ensure that [`FetchState::update_component_access`] and
436-
/// [`FetchState::update_archetype_component_access`] exactly reflects the results of
437-
/// [`FetchState::matches_archetype`], [`FetchState::matches_table`], [`Fetch::archetype_fetch`], and
438-
/// [`Fetch::table_fetch`].
439-
pub unsafe trait FetchState: Send + Sync + Sized {
438+
pub trait FetchState: Send + Sync + Sized {
440439
fn init(world: &mut World) -> Self;
441440
fn matches_archetype(&self, archetype: &Archetype) -> bool;
442441
fn matches_table(&self, table: &Table) -> bool;
443442
}
444443

445-
impl WorldQuery for Entity {
444+
/// SAFETY: no component or archetype access
445+
unsafe impl WorldQuery for Entity {
446446
type ReadOnly = Self;
447447
type State = EntityState;
448448

@@ -474,8 +474,7 @@ unsafe impl ReadOnlyWorldQuery for Entity {}
474474
#[doc(hidden)]
475475
pub struct EntityState;
476476

477-
// SAFETY: no component or archetype access
478-
unsafe impl FetchState for EntityState {
477+
impl FetchState for EntityState {
479478
fn init(_world: &mut World) -> Self {
480479
Self
481480
}
@@ -541,7 +540,9 @@ impl<'w> Fetch<'w> for EntityFetch<'w> {
541540
}
542541
}
543542

544-
impl<T: Component> WorldQuery for &T {
543+
// SAFETY: component access and archetype component access are properly updated to reflect that T is
544+
// read
545+
unsafe impl<T: Component> WorldQuery for &T {
545546
type ReadOnly = Self;
546547
type State = ReadState<T>;
547548

@@ -578,9 +579,7 @@ pub struct ReadState<T> {
578579
marker: PhantomData<T>,
579580
}
580581

581-
// SAFETY: component access and archetype component access are properly updated to reflect that T is
582-
// read
583-
unsafe impl<T: Component> FetchState for ReadState<T> {
582+
impl<T: Component> FetchState for ReadState<T> {
584583
fn init(world: &mut World) -> Self {
585584
let component_id = world.init_component::<T>();
586585
ReadState {
@@ -725,7 +724,9 @@ impl<'w, T: Component> Fetch<'w> for ReadFetch<'w, T> {
725724
}
726725
}
727726

728-
impl<'w, T: Component> WorldQuery for &'w mut T {
727+
/// SAFETY: component access and archetype component access are properly updated to reflect that T is
728+
/// read and write
729+
unsafe impl<'w, T: Component> WorldQuery for &'w mut T {
729730
type ReadOnly = &'w T;
730731
type State = ReadState<T>;
731732

@@ -908,7 +909,9 @@ impl<'w, 's, T: Component> Fetch<'w> for WriteFetch<'w, T> {
908909
}
909910
}
910911

911-
impl<T: WorldQuery> WorldQuery for Option<T> {
912+
// SAFETY: component access and archetype component access are properly updated according to the
913+
// internal Fetch
914+
unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
912915
type ReadOnly = Option<T::ReadOnly>;
913916
type State = OptionState<T::State>;
914917

@@ -948,9 +951,7 @@ pub struct OptionState<T: FetchState> {
948951
state: T,
949952
}
950953

951-
// SAFETY: component access and archetype component access are properly updated according to the
952-
// internal Fetch
953-
unsafe impl<T: FetchState> FetchState for OptionState<T> {
954+
impl<T: FetchState> FetchState for OptionState<T> {
954955
fn init(world: &mut World) -> Self {
955956
Self {
956957
state: T::init(world),
@@ -1095,7 +1096,9 @@ impl<T: Component> ChangeTrackers<T> {
10951096
}
10961097
}
10971098

1098-
impl<T: Component> WorldQuery for ChangeTrackers<T> {
1099+
// SAFETY: component access and archetype component access are properly updated to reflect that T is
1100+
// read
1101+
unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
10991102
type ReadOnly = Self;
11001103
type State = ChangeTrackersState<T>;
11011104

@@ -1132,9 +1135,7 @@ pub struct ChangeTrackersState<T> {
11321135
marker: PhantomData<T>,
11331136
}
11341137

1135-
// SAFETY: component access and archetype component access are properly updated to reflect that T is
1136-
// read
1137-
unsafe impl<T: Component> FetchState for ChangeTrackersState<T> {
1138+
impl<T: Component> FetchState for ChangeTrackersState<T> {
11381139
fn init(world: &mut World) -> Self {
11391140
let component_id = world.init_component::<T>();
11401141
Self {
@@ -1377,10 +1378,9 @@ macro_rules! impl_tuple_fetch {
13771378
}
13781379
}
13791380

1380-
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
13811381
#[allow(non_snake_case)]
13821382
#[allow(clippy::unused_unit)]
1383-
unsafe impl<$($name: FetchState),*> FetchState for ($($name,)*) {
1383+
impl<$($name: FetchState),*> FetchState for ($($name,)*) {
13841384
fn init(_world: &mut World) -> Self {
13851385
($($name::init(_world),)*)
13861386
}
@@ -1398,7 +1398,8 @@ macro_rules! impl_tuple_fetch {
13981398

13991399
#[allow(non_snake_case)]
14001400
#[allow(clippy::unused_unit)]
1401-
impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
1401+
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
1402+
unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
14021403
type ReadOnly = ($($name::ReadOnly,)*);
14031404
type State = ($($name::State,)*);
14041405

@@ -1500,10 +1501,9 @@ macro_rules! impl_anytuple_fetch {
15001501
}
15011502
}
15021503

1503-
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
15041504
#[allow(non_snake_case)]
15051505
#[allow(clippy::unused_unit)]
1506-
unsafe impl<$($name: FetchState),*> FetchState for AnyOf<($($name,)*)> {
1506+
impl<$($name: FetchState),*> FetchState for AnyOf<($($name,)*)> {
15071507
fn init(_world: &mut World) -> Self {
15081508
AnyOf(($($name::init(_world),)*))
15091509
}
@@ -1521,7 +1521,8 @@ macro_rules! impl_anytuple_fetch {
15211521

15221522
#[allow(non_snake_case)]
15231523
#[allow(clippy::unused_unit)]
1524-
impl<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> {
1524+
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
1525+
unsafe impl<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> {
15251526
type ReadOnly = AnyOf<($($name::ReadOnly,)*)>;
15261527
type State = AnyOf<($($name::State,)*)>;
15271528

crates/bevy_ecs/src/query/filter.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ use super::ReadOnlyWorldQuery;
4444
/// ```
4545
pub struct With<T>(PhantomData<T>);
4646

47-
impl<T: Component> WorldQuery for With<T> {
47+
// SAFETY: no component access or archetype component access
48+
unsafe impl<T: Component> WorldQuery for With<T> {
4849
type ReadOnly = Self;
4950
type State = WithState<T>;
5051

@@ -81,8 +82,7 @@ pub struct WithState<T> {
8182
marker: PhantomData<T>,
8283
}
8384

84-
// SAFETY: no component access or archetype component access
85-
unsafe impl<T: Component> FetchState for WithState<T> {
85+
impl<T: Component> FetchState for WithState<T> {
8686
fn init(world: &mut World) -> Self {
8787
let component_id = world.init_component::<T>();
8888
Self {
@@ -187,7 +187,8 @@ impl<T> Copy for WithFetch<T> {}
187187
/// ```
188188
pub struct Without<T>(PhantomData<T>);
189189

190-
impl<T: Component> WorldQuery for Without<T> {
190+
// SAFETY: no component access or archetype component access
191+
unsafe impl<T: Component> WorldQuery for Without<T> {
191192
type ReadOnly = Self;
192193
type State = WithoutState<T>;
193194

@@ -224,8 +225,7 @@ pub struct WithoutState<T> {
224225
marker: PhantomData<T>,
225226
}
226227

227-
// SAFETY: no component access or archetype component access
228-
unsafe impl<T: Component> FetchState for WithoutState<T> {
228+
impl<T: Component> FetchState for WithoutState<T> {
229229
fn init(world: &mut World) -> Self {
230230
let component_id = world.init_component::<T>();
231231
Self {
@@ -350,7 +350,8 @@ macro_rules! impl_query_filter_tuple {
350350
($(($filter: ident, $state: ident)),*) => {
351351
#[allow(unused_variables)]
352352
#[allow(non_snake_case)]
353-
impl<$($filter: WorldQuery),*> WorldQuery for Or<($($filter,)*)> {
353+
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
354+
unsafe impl<$($filter: WorldQuery),*> WorldQuery for Or<($($filter,)*)> {
354355
type ReadOnly = Or<($($filter::ReadOnly,)*)>;
355356
type State = Or<($($filter::State,)*)>;
356357

@@ -442,10 +443,9 @@ macro_rules! impl_query_filter_tuple {
442443
}
443444
}
444445

445-
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
446446
#[allow(unused_variables)]
447447
#[allow(non_snake_case)]
448-
unsafe impl<$($filter: FetchState),*> FetchState for Or<($($filter,)*)> {
448+
impl<$($filter: FetchState),*> FetchState for Or<($($filter,)*)> {
449449
fn init(world: &mut World) -> Self {
450450
Or(($($filter::init(world),)*))
451451
}
@@ -500,7 +500,8 @@ macro_rules! impl_tick_filter {
500500
marker: PhantomData<T>,
501501
}
502502

503-
impl<T: Component> WorldQuery for $name<T> {
503+
// SAFETY: this reads the T component. archetype component access and component access are updated to reflect that
504+
unsafe impl<T: Component> WorldQuery for $name<T> {
504505
type ReadOnly = Self;
505506
type State = $state_name<T>;
506507

@@ -529,8 +530,7 @@ macro_rules! impl_tick_filter {
529530
}
530531
}
531532

532-
// SAFETY: this reads the T component. archetype component access and component access are updated to reflect that
533-
unsafe impl<T: Component> FetchState for $state_name<T> {
533+
impl<T: Component> FetchState for $state_name<T> {
534534
fn init(world: &mut World) -> Self {
535535
Self {
536536
component_id: world.init_component::<T>(),

0 commit comments

Comments
 (0)