Skip to content

Commit c0751ed

Browse files
committed
Remove ReadOnlyFetch
1 parent caef967 commit c0751ed

File tree

9 files changed

+400
-484
lines changed

9 files changed

+400
-484
lines changed

crates/bevy_ecs/macros/src/fetch.rs

+78-23
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
9090
user_generics_with_world.split_for_impl();
9191

9292
let struct_name = ast.ident.clone();
93+
let read_only_struct_name = if fetch_struct_attributes.is_mutable {
94+
Ident::new(&format!("{}ReadOnly", struct_name), Span::call_site())
95+
} else {
96+
struct_name.clone()
97+
};
9398

9499
let item_struct_name = Ident::new(&format!("{}Item", struct_name), Span::call_site());
95100
let read_only_item_struct_name = if fetch_struct_attributes.is_mutable {
@@ -262,23 +267,14 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
262267
#(#ignored_field_idents: #ignored_field_types,)*
263268
}
264269

265-
// SAFETY: `update_component_access` and `update_archetype_component_access` are called for each item in the struct
266-
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 {
267271
fn init(world: &mut #path::world::World) -> Self {
268272
#state_struct_name {
269273
#(#field_idents: <<#field_types as #path::query::WorldQuery>::State as #path::query::FetchState>::init(world),)*
270274
#(#ignored_field_idents: Default::default(),)*
271275
}
272276
}
273277

274-
fn update_component_access(&self, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
275-
#(self.#field_idents.update_component_access(_access);)*
276-
}
277-
278-
fn update_archetype_component_access(&self, _archetype: &#path::archetype::Archetype, _access: &mut #path::query::Access<#path::archetype::ArchetypeComponentId>) {
279-
#(self.#field_idents.update_archetype_component_access(_archetype, _access);)*
280-
}
281-
282278
fn matches_component_set(&self, _set_contains_id: &impl Fn(#path::component::ComponentId) -> bool) -> bool {
283279
true #(&& self.#field_idents.matches_component_set(_set_contains_id))*
284280

@@ -290,29 +286,77 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
290286
impl_fetch(
291287
true,
292288
read_only_fetch_struct_name.clone(),
293-
read_only_item_struct_name,
289+
read_only_item_struct_name.clone(),
294290
)
295291
} else {
296292
quote! {}
297293
};
298294

295+
let read_only_world_query_impl = if fetch_struct_attributes.is_mutable {
296+
quote! {
297+
#[automatically_derived]
298+
#visibility struct #read_only_struct_name #user_impl_generics #user_where_clauses {
299+
#( #field_idents: < #field_types as #path::query::WorldQuery >::ReadOnly, )*
300+
#(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)*
301+
}
302+
303+
// SAFETY: `update_component_access` and `update_archetype_component_access` are called on every field
304+
unsafe impl #user_impl_generics #path::query::WorldQuery for #read_only_struct_name #user_ty_generics #user_where_clauses {
305+
type ReadOnly = Self;
306+
type State = #state_struct_name #user_ty_generics;
307+
308+
fn shrink<'__wlong: '__wshort, '__wshort>(item: #path::query::#item_type_alias<'__wlong, Self>)
309+
-> #path::query::#item_type_alias<'__wshort, Self> {
310+
#read_only_item_struct_name {
311+
#(
312+
#field_idents : <
313+
< #field_types as #path::query::WorldQuery >::ReadOnly as #path::query::WorldQuery
314+
> :: shrink( item.#field_idents ),
315+
)*
316+
#(
317+
#ignored_field_idents: item.#ignored_field_idents,
318+
)*
319+
}
320+
}
321+
322+
fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
323+
#( < #field_types as #path::query::WorldQuery > :: ReadOnly :: update_component_access(&state.#field_idents, _access);)*
324+
}
325+
326+
fn update_archetype_component_access(state: &Self::State, _archetype: &#path::archetype::Archetype, _access: &mut #path::query::Access<#path::archetype::ArchetypeComponentId>) {
327+
#(
328+
< #field_types as #path::query::WorldQuery> :: ReadOnly
329+
:: update_archetype_component_access(&state.#field_idents, _archetype, _access);
330+
)*
331+
}
332+
}
333+
334+
impl #user_impl_generics_with_world #path::query::WorldQueryGats<'__w> for #read_only_struct_name #user_ty_generics #user_where_clauses {
335+
type Fetch = #read_only_fetch_struct_name #user_ty_generics_with_world;
336+
type _State = #state_struct_name #user_ty_generics;
337+
}
338+
}
339+
} else {
340+
quote! {}
341+
};
342+
299343
let read_only_asserts = if fetch_struct_attributes.is_mutable {
300344
quote! {
301-
// Double-check that the data fetched by `ROQueryFetch` is read-only.
302-
// This is technically unnecessary as `<_ as WorldQueryGats<'world>>::ReadOnlyFetch: ReadOnlyFetch`
303-
// but to protect against future mistakes we assert the assoc type implements `ReadOnlyFetch` anyway
304-
#( assert_readonly::<#path::query::ROQueryFetch<'__w, #field_types>>(); )*
345+
// Double-check that the data fetched by `<_ as WorldQuery>::ReadOnly` is read-only.
346+
// This is technically unnecessary as `<_ as WorldQuery>::ReadOnly: ReadOnlyWorldQuery`
347+
// but to protect against future mistakes we assert the assoc type implements `ReadOnlyWorldQuery` anyway
348+
#( assert_readonly::< < #field_types as #path::query::WorldQuery > :: ReadOnly >(); )*
305349
}
306350
} else {
307351
quote! {
308-
// Statically checks that the safety guarantee of `ReadOnlyFetch` for `$fetch_struct_name` actually holds true.
309-
// We need this to make sure that we don't compile `ReadOnlyFetch` if our struct contains nested `WorldQuery`
352+
// Statically checks that the safety guarantee of `ReadOnlyWorldQuery` for `$fetch_struct_name` actually holds true.
353+
// We need this to make sure that we don't compile `ReadOnlyWorldQuery` if our struct contains nested `WorldQuery`
310354
// members that don't implement it. I.e.:
311355
// ```
312356
// #[derive(WorldQuery)]
313357
// pub struct Foo { a: &'static mut MyComponent }
314358
// ```
315-
#( assert_readonly::<#path::query::QueryFetch<'__w, #field_types>>(); )*
359+
#( assert_readonly::<#field_types>(); )*
316360
}
317361
};
318362

@@ -323,7 +367,11 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
323367

324368
#read_only_fetch_impl
325369

326-
impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses {
370+
#read_only_world_query_impl
371+
372+
// SAFETY: `update_component_access` and `update_archetype_component_access` are called on every field
373+
unsafe impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses {
374+
type ReadOnly = #read_only_struct_name #user_ty_generics;
327375
type State = #state_struct_name #user_ty_generics;
328376
fn shrink<'__wlong: '__wshort, '__wshort>(item: #path::query::#item_type_alias<'__wlong, Self>)
329377
-> #path::query::#item_type_alias<'__wshort, Self> {
@@ -336,23 +384,30 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
336384
)*
337385
}
338386
}
387+
388+
fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
389+
#(< #field_types as WorldQuery > :: update_component_access(&state.#field_idents, _access);)*
390+
}
391+
392+
fn update_archetype_component_access(state: &Self::State, _archetype: &#path::archetype::Archetype, _access: &mut #path::query::Access<#path::archetype::ArchetypeComponentId>) {
393+
#(< #field_types as WorldQuery > :: update_archetype_component_access(&state.#field_idents, _archetype, _access);)*
394+
}
339395
}
340396

341397
impl #user_impl_generics_with_world #path::query::WorldQueryGats<'__w> for #struct_name #user_ty_generics #user_where_clauses {
342398
type Fetch = #fetch_struct_name #user_ty_generics_with_world;
343-
type ReadOnlyFetch = #read_only_fetch_struct_name #user_ty_generics_with_world;
344399
type _State = #state_struct_name #user_ty_generics;
345400
}
346401

347402
/// SAFETY: each item in the struct is read only
348-
unsafe impl #user_impl_generics_with_world #path::query::ReadOnlyFetch
349-
for #read_only_fetch_struct_name #user_ty_generics_with_world #user_where_clauses_with_world {}
403+
unsafe impl #user_impl_generics #path::query::ReadOnlyWorldQuery
404+
for #read_only_struct_name #user_ty_generics #user_where_clauses {}
350405

351406
#[allow(dead_code)]
352407
const _: () = {
353408
fn assert_readonly<T>()
354409
where
355-
T: #path::query::ReadOnlyFetch,
410+
T: #path::query::ReadOnlyWorldQuery,
356411
{
357412
}
358413

0 commit comments

Comments
 (0)