@@ -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 {
@@ -271,14 +276,6 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
271
276
}
272
277
}
273
278
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
279
fn matches_archetype( & self , _archetype: & #path:: archetype:: Archetype ) -> bool {
283
280
true #( && self . #field_idents. matches_archetype( _archetype) ) *
284
281
}
@@ -293,29 +290,76 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
293
290
impl_fetch (
294
291
true ,
295
292
read_only_fetch_struct_name. clone ( ) ,
296
- read_only_item_struct_name,
293
+ read_only_item_struct_name. clone ( ) ,
297
294
)
298
295
} else {
299
296
quote ! { }
300
297
} ;
301
298
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
+
302
346
let read_only_asserts = if fetch_struct_attributes. is_mutable {
303
347
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 >( ) ; ) *
308
352
}
309
353
} else {
310
354
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`
313
357
// members that don't implement it. I.e.:
314
358
// ```
315
359
// #[derive(WorldQuery)]
316
360
// pub struct Foo { a: &'static mut MyComponent }
317
361
// ```
318
- #( assert_readonly:: <#path :: query :: QueryFetch < ' __w , # field_types> >( ) ; ) *
362
+ #( assert_readonly:: <#field_types>( ) ; ) *
319
363
}
320
364
} ;
321
365
@@ -326,7 +370,10 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
326
370
327
371
#read_only_fetch_impl
328
372
373
+ #read_only_world_query_impl
374
+
329
375
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;
330
377
type State = #state_struct_name #user_ty_generics;
331
378
fn shrink<' __wlong: ' __wshort, ' __wshort>( item: #path:: query:: #item_type_alias<' __wlong, Self >)
332
379
-> #path:: query:: #item_type_alias<' __wshort, Self > {
@@ -339,23 +386,30 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
339
386
) *
340
387
}
341
388
}
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
+ }
342
397
}
343
398
344
399
impl #user_impl_generics_with_world #path:: query:: WorldQueryGats <' __w> for #struct_name #user_ty_generics #user_where_clauses {
345
400
type Fetch = #fetch_struct_name #user_ty_generics_with_world;
346
- type ReadOnlyFetch = #read_only_fetch_struct_name #user_ty_generics_with_world;
347
401
type _State = #state_struct_name #user_ty_generics;
348
402
}
349
403
350
404
/// 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 { }
353
407
354
408
#[ allow( dead_code) ]
355
409
const _: ( ) = {
356
410
fn assert_readonly<T >( )
357
411
where
358
- T : #path:: query:: ReadOnlyFetch ,
412
+ T : #path:: query:: ReadOnlyWorldQuery ,
359
413
{
360
414
}
361
415
0 commit comments