@@ -12,7 +12,7 @@ use proc_macro2::Span;
1212use quote:: { format_ident, quote} ;
1313use syn:: {
1414 parse:: ParseStream , parse_macro_input, parse_quote, punctuated:: Punctuated , spanned:: Spanned ,
15- ConstParam , DeriveInput , Field , GenericParam , Ident , Index , Meta , MetaList , NestedMeta , Token ,
15+ ConstParam , DeriveInput , GenericParam , Ident , Index , Meta , MetaList , NestedMeta , Token ,
1616 TypeParam ,
1717} ;
1818
@@ -259,7 +259,7 @@ static SYSTEM_PARAM_ATTRIBUTE_NAME: &str = "system_param";
259259#[ proc_macro_derive( SystemParam , attributes( system_param) ) ]
260260pub fn derive_system_param ( input : TokenStream ) -> TokenStream {
261261 let ast = parse_macro_input ! ( input as DeriveInput ) ;
262- let syn:: Data :: Struct ( syn:: DataStruct { fields : field_definitions, ..} ) = ast. data else {
262+ let syn:: Data :: Struct ( syn:: DataStruct { fields : field_definitions, .. } ) = ast. data else {
263263 return syn:: Error :: new ( ast. span ( ) , "Invalid `SystemParam` type: expected a `struct`" )
264264 . into_compile_error ( )
265265 . into ( ) ;
@@ -290,7 +290,8 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
290290 } ) ,
291291 )
292292 } )
293- . collect :: < Vec < ( & Field , SystemParamFieldAttributes ) > > ( ) ;
293+ . collect :: < Vec < _ > > ( ) ;
294+
294295 let mut field_locals = Vec :: new ( ) ;
295296 let mut fields = Vec :: new ( ) ;
296297 let mut field_types = Vec :: new ( ) ;
@@ -341,11 +342,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
341342 . filter ( |g| !matches ! ( g, GenericParam :: Lifetime ( _) ) )
342343 . collect ( ) ;
343344
344- let mut shadowed_lifetimes: Vec < _ > = generics. lifetimes ( ) . map ( |x| x. lifetime . clone ( ) ) . collect ( ) ;
345- for lifetime in & mut shadowed_lifetimes {
346- let shadowed_ident = format_ident ! ( "_{}" , lifetime. ident) ;
347- lifetime. ident = shadowed_ident;
348- }
345+ let shadowed_lifetimes: Vec < _ > = generics. lifetimes ( ) . map ( |_| quote ! ( ' _) ) . collect ( ) ;
349346
350347 let mut punctuated_generics = Punctuated :: < _ , Token ! [ , ] > :: new ( ) ;
351348 punctuated_generics. extend ( lifetimeless_generics. iter ( ) . map ( |g| match g {
@@ -367,9 +364,27 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
367364 _ => unreachable ! ( ) ,
368365 } ) ) ;
369366
367+ let punctuated_generics_no_bounds: Punctuated < _ , Token ! [ , ] > = lifetimeless_generics
368+ . iter ( )
369+ . map ( |& g| match g. clone ( ) {
370+ GenericParam :: Type ( mut g) => {
371+ g. bounds . clear ( ) ;
372+ GenericParam :: Type ( g)
373+ }
374+ g => g,
375+ } )
376+ . collect ( ) ;
377+
370378 let mut tuple_types: Vec < _ > = field_types. iter ( ) . map ( |x| quote ! { #x } ) . collect ( ) ;
371379 let mut tuple_patterns: Vec < _ > = field_locals. iter ( ) . map ( |x| quote ! { #x } ) . collect ( ) ;
372380
381+ tuple_types. extend (
382+ ignored_field_types
383+ . iter ( )
384+ . map ( |ty| parse_quote ! ( :: std:: marker:: PhantomData :: <#ty>) ) ,
385+ ) ;
386+ tuple_patterns. extend ( ignored_field_types. iter ( ) . map ( |_| parse_quote ! ( _) ) ) ;
387+
373388 // If the number of fields exceeds the 16-parameter limit,
374389 // fold the fields into tuples of tuples until we are below the limit.
375390 const LIMIT : usize = 16 ;
@@ -380,6 +395,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
380395 let end = Vec :: from_iter ( tuple_patterns. drain ( ..LIMIT ) ) ;
381396 tuple_patterns. push ( parse_quote ! ( ( #( #end, ) * ) ) ) ;
382397 }
398+
383399 // Create a where clause for the `ReadOnlySystemParam` impl.
384400 // Ensure that each field implements `ReadOnlySystemParam`.
385401 let mut read_only_generics = generics. clone ( ) ;
@@ -390,6 +406,8 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
390406 . push ( syn:: parse_quote!( #field_type: #path:: system:: ReadOnlySystemParam ) ) ;
391407 }
392408
409+ let fields_alias = format_ident ! ( "__StructFieldsAlias" ) ;
410+
393411 let struct_name = & ast. ident ;
394412 let state_struct_visibility = & ast. vis ;
395413
@@ -398,41 +416,41 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
398416 // The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via
399417 // <EventReader<'static, 'static, T> as SystemParam>::State
400418 const _: ( ) = {
419+ // Allows rebinding the lifetimes of each field type.
420+ type #fields_alias <' w, ' s, #punctuated_generics_no_bounds> = ( #( #tuple_types, ) * ) ;
421+
401422 #[ doc( hidden) ]
402- #state_struct_visibility struct FetchState <' w , ' s , #( #lifetimeless_generics, ) * >
423+ #state_struct_visibility struct FetchState <#( #lifetimeless_generics, ) * >
403424 #where_clause {
404- state: ( #( <#tuple_types as #path:: system:: SystemParam >:: State , ) * ) ,
405- marker: std:: marker:: PhantomData <(
406- <#path:: prelude:: Query <' w, ' s, ( ) > as #path:: system:: SystemParam >:: State ,
407- #( fn ( ) -> #ignored_field_types, ) *
408- ) >,
425+ state: <#fields_alias:: <' static , ' static , #punctuated_generic_idents> as #path:: system:: SystemParam >:: State ,
409426 }
410427
411- unsafe impl <' w, ' s, #punctuated_generics> #path:: system:: SystemParam for #struct_name #ty_generics #where_clause {
412- type State = FetchState <' static , ' static , #punctuated_generic_idents>;
413- type Item <' _w, ' _s> = #struct_name <#( #shadowed_lifetimes, ) * #punctuated_generic_idents>;
428+ unsafe impl <#punctuated_generics> #path:: system:: SystemParam for
429+ #struct_name <#( #shadowed_lifetimes, ) * #punctuated_generic_idents> #where_clause
430+ {
431+ type State = FetchState <#punctuated_generic_idents>;
432+ type Item <' w, ' s> = #struct_name #ty_generics;
414433
415434 fn init_state( world: & mut #path:: world:: World , system_meta: & mut #path:: system:: SystemMeta ) -> Self :: State {
416435 FetchState {
417- state: <( #( #tuple_types, ) * ) as #path:: system:: SystemParam >:: init_state( world, system_meta) ,
418- marker: std:: marker:: PhantomData ,
436+ state: <#fields_alias:: <' _, ' _, #punctuated_generic_idents> as #path:: system:: SystemParam >:: init_state( world, system_meta) ,
419437 }
420438 }
421439
422440 fn new_archetype( state: & mut Self :: State , archetype: & #path:: archetype:: Archetype , system_meta: & mut #path:: system:: SystemMeta ) {
423- <( # ( #tuple_types , ) * ) as #path:: system:: SystemParam >:: new_archetype( & mut state. state, archetype, system_meta)
441+ <#fields_alias :: < ' _ , ' _ , #punctuated_generic_idents> as #path:: system:: SystemParam >:: new_archetype( & mut state. state, archetype, system_meta)
424442 }
425443
426444 fn apply( state: & mut Self :: State , system_meta: & #path:: system:: SystemMeta , world: & mut #path:: world:: World ) {
427- <( # ( #tuple_types , ) * ) as #path:: system:: SystemParam >:: apply( & mut state. state, system_meta, world) ;
445+ <#fields_alias :: < ' _ , ' _ , #punctuated_generic_idents> as #path:: system:: SystemParam >:: apply( & mut state. state, system_meta, world) ;
428446 }
429447
430- unsafe fn get_param<' w2 , ' s2 >(
431- state: & ' s2 mut Self :: State ,
448+ unsafe fn get_param<' w , ' s >(
449+ state: & ' s mut Self :: State ,
432450 system_meta: & #path:: system:: SystemMeta ,
433- world: & ' w2 #path:: world:: World ,
451+ world: & ' w #path:: world:: World ,
434452 change_tick: u32 ,
435- ) -> Self :: Item <' w2 , ' s2 > {
453+ ) -> Self :: Item <' w , ' s > {
436454 let ( #( #tuple_patterns, ) * ) = <
437455 ( #( #tuple_types, ) * ) as #path:: system:: SystemParam
438456 >:: get_param( & mut state. state, system_meta, world, change_tick) ;
0 commit comments