Skip to content

Commit b735bea

Browse files
committed
Remove ReadOnlyFetch
1 parent 990d5c0 commit b735bea

File tree

7 files changed

+302
-387
lines changed

7 files changed

+302
-387
lines changed

crates/bevy_ecs/macros/src/fetch.rs

+74-20
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 {
@@ -271,14 +276,6 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
271276
}
272277
}
273278

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-
282279
fn matches_archetype(&self, _archetype: &#path::archetype::Archetype) -> bool {
283280
true #(&& self.#field_idents.matches_archetype(_archetype))*
284281
}
@@ -293,29 +290,76 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
293290
impl_fetch(
294291
true,
295292
read_only_fetch_struct_name.clone(),
296-
read_only_item_struct_name,
293+
read_only_item_struct_name.clone(),
297294
)
298295
} else {
299296
quote! {}
300297
};
301298

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

@@ -326,7 +370,10 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
326370

327371
#read_only_fetch_impl
328372

373+
#read_only_world_query_impl
374+
329375
impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses {
376+
type ReadOnly = #read_only_struct_name #user_ty_generics;
330377
type State = #state_struct_name #user_ty_generics;
331378
fn shrink<'__wlong: '__wshort, '__wshort>(item: #path::query::#item_type_alias<'__wlong, Self>)
332379
-> #path::query::#item_type_alias<'__wshort, Self> {
@@ -339,23 +386,30 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
339386
)*
340387
}
341388
}
389+
390+
fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
391+
#(< #field_types as WorldQuery > :: update_component_access(&state.#field_idents, _access);)*
392+
}
393+
394+
fn update_archetype_component_access(state: &Self::State, _archetype: &#path::archetype::Archetype, _access: &mut #path::query::Access<#path::archetype::ArchetypeComponentId>) {
395+
#(< #field_types as WorldQuery > :: update_archetype_component_access(&state.#field_idents, _archetype, _access);)*
396+
}
342397
}
343398

344399
impl #user_impl_generics_with_world #path::query::WorldQueryGats<'__w> for #struct_name #user_ty_generics #user_where_clauses {
345400
type Fetch = #fetch_struct_name #user_ty_generics_with_world;
346-
type ReadOnlyFetch = #read_only_fetch_struct_name #user_ty_generics_with_world;
347401
type _State = #state_struct_name #user_ty_generics;
348402
}
349403

350404
/// SAFETY: each item in the struct is read only
351-
unsafe impl #user_impl_generics_with_world #path::query::ReadOnlyFetch
352-
for #read_only_fetch_struct_name #user_ty_generics_with_world #user_where_clauses_with_world {}
405+
unsafe impl #user_impl_generics #path::query::ReadOnlyWorldQuery
406+
for #read_only_struct_name #user_ty_generics #user_where_clauses {}
353407

354408
#[allow(dead_code)]
355409
const _: () = {
356410
fn assert_readonly<T>()
357411
where
358-
T: #path::query::ReadOnlyFetch,
412+
T: #path::query::ReadOnlyWorldQuery,
359413
{
360414
}
361415

0 commit comments

Comments
 (0)