From 673a62744e26f18f3fcfb174c13c5a1e323dd364 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:49:42 -0400 Subject: [PATCH] Fix field visibility for read-only `WorldQuery` types (#8163) When using the `#[derive(WorldQuery)]` macro, the `ReadOnly` struct generated has default (private) visibility for each field, regardless of the visibility of the original field. For each field of a read-only `WorldQuery` variant, use the visibility of the associated field defined on the original struct. --- crates/bevy_ecs/macros/src/fetch.rs | 2 +- crates/bevy_ecs/src/query/fetch.rs | 34 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/macros/src/fetch.rs b/crates/bevy_ecs/macros/src/fetch.rs index 418c5741e7..03cfba5179 100644 --- a/crates/bevy_ecs/macros/src/fetch.rs +++ b/crates/bevy_ecs/macros/src/fetch.rs @@ -336,7 +336,7 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream { #[doc = "`]."] #[automatically_derived] #visibility struct #read_only_struct_name #user_impl_generics #user_where_clauses { - #( #field_idents: #read_only_field_types, )* + #( #field_visibilities #field_idents: #read_only_field_types, )* #(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)* } diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 7e4c7a3f74..02229420fa 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -1642,3 +1642,37 @@ unsafe impl WorldQuery for NopWorldQuery { /// SAFETY: `NopFetch` never accesses any data unsafe impl ReadOnlyWorldQuery for NopWorldQuery {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{self as bevy_ecs, system::Query}; + + #[derive(Component)] + pub struct A; + + // Ensures that each field of a `WorldQuery` struct's read-only variant + // has the same visibility as its corresponding mutable field. + #[test] + fn read_only_field_visibility() { + mod private { + use super::*; + + #[derive(WorldQuery)] + #[world_query(mutable)] + pub struct Q { + pub a: &'static mut A, + } + } + + let _ = private::QReadOnly { a: &A }; + + fn my_system(query: Query) { + for q in &query { + let _ = &q.a; + } + } + + crate::system::assert_is_system(my_system); + } +}