@@ -90,6 +90,11 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
90
90
user_generics_with_world. split_for_impl ( ) ;
91
91
92
92
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
+ } ;
93
98
94
99
let item_struct_name = Ident :: new ( & format ! ( "{}Item" , struct_name) , Span :: call_site ( ) ) ;
95
100
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 {
262
267
#( #ignored_field_idents: #ignored_field_types, ) *
263
268
}
264
269
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 {
267
271
fn init( world: & mut #path:: world:: World ) -> Self {
268
272
#state_struct_name {
269
273
#( #field_idents: <<#field_types as #path:: query:: WorldQuery >:: State as #path:: query:: FetchState >:: init( world) , ) *
270
274
#( #ignored_field_idents: Default :: default ( ) , ) *
271
275
}
272
276
}
273
277
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
-
282
278
fn matches_component_set( & self , _set_contains_id: & impl Fn ( #path:: component:: ComponentId ) -> bool ) -> bool {
283
279
true #( && self . #field_idents. matches_component_set( _set_contains_id) ) *
284
280
@@ -290,29 +286,77 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
290
286
impl_fetch (
291
287
true ,
292
288
read_only_fetch_struct_name. clone ( ) ,
293
- read_only_item_struct_name,
289
+ read_only_item_struct_name. clone ( ) ,
294
290
)
295
291
} else {
296
292
quote ! { }
297
293
} ;
298
294
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
+
299
343
let read_only_asserts = if fetch_struct_attributes. is_mutable {
300
344
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 >( ) ; ) *
305
349
}
306
350
} else {
307
351
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`
310
354
// members that don't implement it. I.e.:
311
355
// ```
312
356
// #[derive(WorldQuery)]
313
357
// pub struct Foo { a: &'static mut MyComponent }
314
358
// ```
315
- #( assert_readonly:: <#path :: query :: QueryFetch < ' __w , # field_types> >( ) ; ) *
359
+ #( assert_readonly:: <#field_types>( ) ; ) *
316
360
}
317
361
} ;
318
362
@@ -323,7 +367,11 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
323
367
324
368
#read_only_fetch_impl
325
369
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;
327
375
type State = #state_struct_name #user_ty_generics;
328
376
fn shrink<' __wlong: ' __wshort, ' __wshort>( item: #path:: query:: #item_type_alias<' __wlong, Self >)
329
377
-> #path:: query:: #item_type_alias<' __wshort, Self > {
@@ -336,23 +384,30 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
336
384
) *
337
385
}
338
386
}
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
+ }
339
395
}
340
396
341
397
impl #user_impl_generics_with_world #path:: query:: WorldQueryGats <' __w> for #struct_name #user_ty_generics #user_where_clauses {
342
398
type Fetch = #fetch_struct_name #user_ty_generics_with_world;
343
- type ReadOnlyFetch = #read_only_fetch_struct_name #user_ty_generics_with_world;
344
399
type _State = #state_struct_name #user_ty_generics;
345
400
}
346
401
347
402
/// 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 { }
350
405
351
406
#[ allow( dead_code) ]
352
407
const _: ( ) = {
353
408
fn assert_readonly<T >( )
354
409
where
355
- T : #path:: query:: ReadOnlyFetch ,
410
+ T : #path:: query:: ReadOnlyWorldQuery ,
356
411
{
357
412
}
358
413
0 commit comments