diff --git a/crates/bevy_ecs/macros/src/fetch.rs b/crates/bevy_ecs/macros/src/fetch.rs index 418c5741e75e2..0308d8dc2338b 100644 --- a/crates/bevy_ecs/macros/src/fetch.rs +++ b/crates/bevy_ecs/macros/src/fetch.rs @@ -176,7 +176,7 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { &field_types }; - quote! { + let item_struct = quote! { #derive_macro_call #[doc = "Automatically generated [`WorldQuery`] item type for [`"] #[doc = stringify!(#struct_name)] @@ -186,7 +186,9 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::WorldQuery>::Item<'__w>,)* #(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)* } + }; + let query_impl = quote! { #[doc(hidden)] #[doc = "Automatically generated internal [`WorldQuery`] fetch type for [`"] #[doc = stringify!(#struct_name)] @@ -324,13 +326,14 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { true #(&& <#field_types>::matches_component_set(&state.#field_idents, _set_contains_id))* } } - } + }; + (item_struct, query_impl) }; - let mutable_impl = impl_fetch(false); - let readonly_impl = if fetch_struct_attributes.is_mutable { - let world_query_impl = impl_fetch(true); - quote! { + let (mutable_struct, mutable_impl) = impl_fetch(false); + let (read_only_struct, read_only_impl) = if fetch_struct_attributes.is_mutable { + let (readonly_state, read_only_impl) = impl_fetch(true); + let read_only_structs = quote! { #[doc = "Automatically generated [`WorldQuery`] type for a read-only variant of [`"] #[doc = stringify!(#struct_name)] #[doc = "`]."] @@ -340,10 +343,11 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { #(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)* } - #world_query_impl - } + #readonly_state + }; + (read_only_structs, read_only_impl) } else { - quote! {} + (quote! {}, quote! {}) }; let read_only_asserts = if fetch_struct_attributes.is_mutable { @@ -367,24 +371,30 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { }; TokenStream::from(quote! { - #mutable_impl - - #readonly_impl - - #[doc(hidden)] - #[doc = "Automatically generated internal [`WorldQuery`] state type for [`"] - #[doc = stringify!(#struct_name)] - #[doc = "`], used for caching."] - #[automatically_derived] - #visibility struct #state_struct_name #user_impl_generics #user_where_clauses { - #(#field_idents: <#field_types as #path::query::WorldQuery>::State,)* - #(#ignored_field_idents: #ignored_field_types,)* - } + #mutable_struct + + #read_only_struct /// SAFETY: we assert fields are readonly below unsafe impl #user_impl_generics #path::query::ReadOnlyWorldQuery for #read_only_struct_name #user_ty_generics #user_where_clauses {} + const _: () = { + #[doc(hidden)] + #[doc = "Automatically generated internal [`WorldQuery`] state type for [`"] + #[doc = stringify!(#struct_name)] + #[doc = "`], used for caching."] + #[automatically_derived] + #visibility struct #state_struct_name #user_impl_generics #user_where_clauses { + #(#field_idents: <#field_types as #path::query::WorldQuery>::State,)* + #(#ignored_field_idents: #ignored_field_types,)* + } + + #mutable_impl + + #read_only_impl + }; + #[allow(dead_code)] const _: () = { fn assert_readonly() @@ -412,7 +422,6 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { #(q.#ignored_field_idents;)* #(q2.#field_idents;)* #(q2.#ignored_field_idents;)* - } }; }) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 7e4c7a3f7434a..9ff765648fea0 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -92,16 +92,13 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// ## Macro expansion /// -/// Expanding the macro will declare three or six additional structs, depending on whether or not the struct is marked as mutable. +/// Expanding the macro will declare one or three additional structs, depending on whether or not the struct is marked as mutable. /// For a struct named `X`, the additional structs will be: /// /// |Struct name|`mutable` only|Description| /// |:---:|:---:|---| -/// |`XState`|---|Used as the [`State`] type for `X` and `XReadOnly`| /// |`XItem`|---|The type of the query item for `X`| -/// |`XFetch`|---|Used as the [`Fetch`] type for `X`| /// |`XReadOnlyItem`|✓|The type of the query item for `XReadOnly`| -/// |`XReadOnlyFetch`|✓|Used as the [`Fetch`] type for `XReadOnly`| /// |`XReadOnly`|✓|[`ReadOnly`] variant of `X`| /// /// ## Adding mutable references @@ -296,7 +293,6 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// [`Added`]: crate::query::Added /// [`fetch`]: Self::fetch /// [`Changed`]: crate::query::Changed -/// [`Fetch`]: crate::query::WorldQuery::Fetch /// [`matches_component_set`]: Self::matches_component_set /// [`Or`]: crate::query::Or /// [`Query`]: crate::system::Query