@@ -322,14 +322,14 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
322
322
}
323
323
324
324
#[ derive( PartialEq , Clone ) ]
325
- enum SystemParamUsage {
325
+ enum SystemParamFieldUsage {
326
326
Ignore ,
327
327
Infallible ,
328
328
Optional ,
329
- Resultful ( Ident ) ,
329
+ Resultful ,
330
330
}
331
331
332
- impl Parse for SystemParamUsage {
332
+ impl Parse for SystemParamFieldUsage {
333
333
fn parse ( input : ParseStream ) -> Result < Self > {
334
334
if input. parse :: < Option < kw:: ignore > > ( ) ?. is_some ( ) {
335
335
return Ok ( Self :: Ignore ) ;
@@ -343,20 +343,58 @@ impl Parse for SystemParamUsage {
343
343
return Ok ( Self :: Optional ) ;
344
344
}
345
345
346
+ if input. parse :: < Option < kw:: resultful > > ( ) ?. is_some ( ) {
347
+ return Ok ( Self :: Resultful ) ;
348
+ }
349
+
350
+ return Err ( input. error ( "Expected one of 'ignore', 'infallible', 'optional', or 'resultful'" ) ) ;
351
+ }
352
+ }
353
+
354
+ impl From < SystemParamStructUsage > for SystemParamFieldUsage {
355
+ fn from ( u : SystemParamStructUsage ) -> Self {
356
+ match u {
357
+ SystemParamStructUsage :: Infallible => SystemParamFieldUsage :: Infallible ,
358
+ SystemParamStructUsage :: Optional => SystemParamFieldUsage :: Optional ,
359
+ SystemParamStructUsage :: Resultful ( _) => SystemParamFieldUsage :: Resultful
360
+ }
361
+ }
362
+ }
363
+
364
+ #[ derive( PartialEq , Clone ) ]
365
+ enum SystemParamStructUsage {
366
+ Infallible ,
367
+ Optional ,
368
+ Resultful ( Ident ) ,
369
+ }
370
+
371
+ impl Parse for SystemParamStructUsage {
372
+ fn parse ( input : ParseStream ) -> Result < Self > {
373
+ if input. parse :: < Option < kw:: infallible > > ( ) ?. is_some ( ) {
374
+ return Ok ( Self :: Infallible ) ;
375
+ }
376
+
377
+ if input. parse :: < Option < kw:: optional > > ( ) ?. is_some ( ) {
378
+ return Ok ( Self :: Optional ) ;
379
+ }
380
+
346
381
if input. parse :: < Option < kw:: resultful > > ( ) ?. is_some ( ) {
347
382
let content;
348
383
parenthesized ! ( content in input) ;
349
- let err_ty = content. parse :: < Ident > ( ) ?;
384
+ let err_ty = match content. parse :: < Ident > ( ) {
385
+ Ok ( o) => o,
386
+ Err ( _) => return Err ( input. error ( "Expected an identifier for `ResultfulSystemParam::Error`." ) )
387
+ } ;
350
388
return Ok ( Self :: Resultful ( err_ty) ) ;
351
389
}
352
390
353
- return Err ( input. error ( "Expected one of 'ignore', ' infallible', 'optional', or 'resultful'" ) ) ;
391
+ return Err ( input. error ( "Expected one of 'infallible', 'optional', or 'resultful(ErrorType) '" ) ) ;
354
392
}
355
393
}
356
394
357
395
#[ derive( Default ) ]
358
396
struct SystemParamAttributes {
359
- pub usage : Option < SystemParamUsage > ,
397
+ pub usage : Option < SystemParamFieldUsage > ,
360
398
}
361
399
362
400
static SYSTEM_PARAM_ATTRIBUTE_NAME : & str = "system_param" ;
@@ -377,13 +415,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
377
415
let Some ( attr_ident) = attr. path . get_ident ( ) else { continue ; } ;
378
416
if attr_ident == SYSTEM_PARAM_ATTRIBUTE_NAME {
379
417
if fallibility. is_none ( ) {
380
- let usage = attr. parse_args_with ( SystemParamUsage :: parse)
381
- . expect ( "Invalid 'system_param' attribute format." ) ;
382
- if usage == SystemParamUsage :: Ignore {
383
- return syn:: Error :: new ( attr. span ( ) , "'ignore' is an invalid option at the struct level." )
384
- . into_compile_error ( )
385
- . into ( ) ;
386
- }
418
+ let usage = match attr. parse_args_with ( SystemParamStructUsage :: parse) {
419
+ Ok ( u) => u,
420
+ Err ( e) => return e. into_compile_error ( ) . into ( ) ,
421
+ } ;
387
422
fallibility = Some ( usage) ;
388
423
} else {
389
424
return syn:: Error :: new ( attr. span ( ) , "Multiple `system_param` struct attributes found." )
@@ -393,18 +428,17 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
393
428
}
394
429
}
395
430
396
- let fallibility = fallibility. clone ( ) . unwrap_or ( SystemParamUsage :: Infallible ) ;
431
+ let fallibility = fallibility. unwrap_or ( SystemParamStructUsage :: Infallible ) ;
397
432
398
433
let associated_error = match fallibility {
399
- SystemParamUsage :: Resultful ( ref err_ty) => quote ! { type Error = #err_ty; } ,
434
+ SystemParamStructUsage :: Resultful ( ref err_ty) => quote ! { type Error = #err_ty; } ,
400
435
_ => quote ! { } ,
401
436
} ;
402
437
403
438
let mut field_idents = Vec :: new ( ) ;
404
439
let mut field_getters = Vec :: new ( ) ;
405
440
let mut field_patterns = Vec :: new ( ) ;
406
441
let mut field_types = Vec :: new ( ) ;
407
- let mut field_wrapped_types = Vec :: new ( ) ;
408
442
let mut ignored_fields = Vec :: new ( ) ;
409
443
let mut ignored_field_types = Vec :: new ( ) ;
410
444
for ( i, field) in fields. iter ( ) . enumerate ( ) {
@@ -413,8 +447,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
413
447
let Some ( attr_ident) = attr. path . get_ident ( ) else { continue ; } ;
414
448
if attr_ident == SYSTEM_PARAM_ATTRIBUTE_NAME {
415
449
if field_attrs. usage . is_none ( ) {
416
- field_attrs. usage = Some ( attr. parse_args_with ( SystemParamUsage :: parse)
417
- . expect ( "Invalid 'system_param' attribute format." ) ) ;
450
+ field_attrs. usage = Some ( match attr. parse_args_with ( SystemParamFieldUsage :: parse) {
451
+ Ok ( o) => o,
452
+ Err ( e) => return e. into_compile_error ( ) . into ( )
453
+ } ) ;
418
454
} else {
419
455
return syn:: Error :: new ( attr. span ( ) , "Multiple `system_param` field attributes found." )
420
456
. into_compile_error ( )
@@ -423,9 +459,14 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
423
459
}
424
460
}
425
461
426
- match field_attrs. usage . unwrap_or ( fallibility. clone ( ) ) {
427
- SystemParamUsage :: Ignore => {
428
- ignored_fields. push ( field. ident . as_ref ( ) . unwrap ( ) ) ;
462
+ match field_attrs. usage . unwrap_or ( fallibility. clone ( ) . into ( ) ) {
463
+ SystemParamFieldUsage :: Ignore => {
464
+ ignored_fields. push ( match field. ident . as_ref ( ) {
465
+ Some ( s) => s,
466
+ None => return syn:: Error :: new ( field. span ( ) , "Field lacks an identifier." )
467
+ . into_compile_error ( )
468
+ . into ( )
469
+ } ) ;
429
470
ignored_field_types. push ( & field. ty ) ;
430
471
} ,
431
472
field_fallibility @ _ => {
@@ -439,30 +480,32 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
439
480
. map ( |f| quote ! { #f } )
440
481
. unwrap_or_else ( || quote ! { #i } ) ,
441
482
) ;
442
- field_types. push ( quote ! { #ty } ) ;
443
- let ( getter, ty) = match fallibility {
444
- SystemParamUsage :: Infallible => match field_fallibility {
445
- SystemParamUsage :: Infallible => ( quote ! { #ident } , quote ! { #ty } ) ,
446
- SystemParamUsage :: Optional => ( quote ! { #ident. expect( "Optional system param was not infallible!" ) } , quote ! { Option <#ty> } ) ,
447
- SystemParamUsage :: Resultful ( _) => ( quote ! { #ident. expect( "Resultful system param was not infallible!" ) } , quote ! { Result <#ty, <#ty as #bevy_ecs:: system:: ResultfulSystemParam >:: Error > } ) ,
448
- SystemParamUsage :: Ignore => unreachable ! ( ) ,
483
+ field_getters. push ( match fallibility {
484
+ SystemParamStructUsage :: Infallible => match field_fallibility {
485
+ SystemParamFieldUsage :: Infallible => quote ! { #ident } ,
486
+ SystemParamFieldUsage :: Optional => quote ! { #ident. expect( "Optional system param was not infallible!" ) } ,
487
+ SystemParamFieldUsage :: Resultful => quote ! { #ident. expect( "Resultful system param was not infallible!" ) } ,
488
+ _ => unreachable ! ( ) ,
449
489
} ,
450
- SystemParamUsage :: Optional => match field_fallibility {
451
- SystemParamUsage :: Infallible => ( quote ! { #ident } , quote ! { #ty } ) ,
452
- SystemParamUsage :: Optional => ( quote ! { match #ident { Some ( s) => s, None => return None , } } , quote ! { Option <#ty> } ) ,
453
- SystemParamUsage :: Resultful ( _ ) => ( quote ! { match #ident { Ok ( o) => o, Err ( _) => return None , } } , quote ! { Result <#ty , <#ty as #bevy_ecs :: system :: ResultfulSystemParam > :: Error > } ) ,
454
- SystemParamUsage :: Ignore => unreachable ! ( ) ,
490
+ SystemParamStructUsage :: Optional => match field_fallibility {
491
+ SystemParamFieldUsage :: Infallible => quote ! { #ident } ,
492
+ SystemParamFieldUsage :: Optional => quote ! { match #ident { Some ( s) => s, None => return None , } } ,
493
+ SystemParamFieldUsage :: Resultful => quote ! { match #ident { Ok ( o) => o, Err ( _) => return None , } } ,
494
+ _ => unreachable ! ( ) ,
455
495
} ,
456
- SystemParamUsage :: Resultful ( _) => match field_fallibility {
457
- SystemParamUsage :: Infallible => ( quote ! { #ident } , quote ! { #ty } ) ,
458
- SystemParamUsage :: Optional => ( quote ! { match #ident { Some ( s) => s, None => return Err ( #bevy_ecs:: system:: SystemParamError :: <#ty>:: default ( ) . into( ) ) , } } , quote ! { Option <#ty> } ) ,
459
- SystemParamUsage :: Resultful ( _ ) => ( quote ! { match #ident { Ok ( o) => o, Err ( e) => return Err ( e. into( ) ) , } } , quote ! { Result <#ty , <#ty as #bevy_ecs :: system :: ResultfulSystemParam > :: Error > } ) ,
460
- SystemParamUsage :: Ignore => unreachable ! ( ) ,
496
+ SystemParamStructUsage :: Resultful ( _) => match field_fallibility {
497
+ SystemParamFieldUsage :: Infallible => quote ! { #ident } ,
498
+ SystemParamFieldUsage :: Optional => quote ! { match #ident { Some ( s) => s, None => return Err ( #bevy_ecs:: system:: SystemParamError :: <#ty>:: default ( ) . into( ) ) , } } ,
499
+ SystemParamFieldUsage :: Resultful => quote ! { match #ident { Ok ( o) => o, Err ( e) => return Err ( e. into( ) ) , } } ,
500
+ _ => unreachable ! ( ) ,
461
501
} ,
462
- SystemParamUsage :: Ignore => unreachable ! ( ) ,
463
- } ;
464
- field_getters. push ( getter) ;
465
- field_wrapped_types. push ( ty) ;
502
+ } ) ;
503
+ field_types. push ( match field_fallibility {
504
+ SystemParamFieldUsage :: Infallible => quote ! { #ty } ,
505
+ SystemParamFieldUsage :: Optional => quote ! { Option <#ty> } ,
506
+ SystemParamFieldUsage :: Resultful => quote ! { Result <#ty, <#ty as #bevy_ecs:: system:: ResultfulSystemParam >:: Error > } ,
507
+ _ => unreachable ! ( ) ,
508
+ } ) ;
466
509
field_patterns. push ( ident) ;
467
510
}
468
511
}
@@ -521,28 +564,34 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
521
564
_ => unreachable ! ( ) ,
522
565
} ) ) ;
523
566
524
- // Create a where clause for the `ReadOnlySystemParam` impl.
525
- // Ensure that each field implements `ReadOnlySystemParam`.
526
- let mut read_only_generics = generics. clone ( ) ;
527
- let read_only_where_clause = read_only_generics. make_where_clause ( ) ;
528
- for field_type in & field_types {
529
- read_only_where_clause
530
- . predicates
531
- . push ( syn:: parse_quote!( #field_type: #bevy_ecs:: system:: ReadOnlySystemParam ) ) ;
532
- }
533
-
534
567
// If the number of fields exceeds the 16-parameter limit,
535
568
// fold the fields into tuples of tuples until we are below the limit.
536
569
const LIMIT : usize = 16 ;
537
570
while field_types. len ( ) > LIMIT {
538
571
let end = Vec :: from_iter ( field_types. drain ( ..LIMIT ) ) ;
539
- field_types. push ( parse_quote ! ( ( #( #end, ) * ) ) ) ;
540
-
541
- let end = Vec :: from_iter ( field_wrapped_types . drain ( .. LIMIT ) ) ;
542
- field_wrapped_types . push ( parse_quote ! ( ( # ( #end , ) * ) ) ) ;
572
+ field_types. push ( match syn :: parse ( quote ! { ( #( #end, ) * ) } . into ( ) ) {
573
+ Ok ( o ) => o ,
574
+ Err ( e ) => return e . into_compile_error ( ) . into ( ) ,
575
+ } ) ;
543
576
544
577
let end = Vec :: from_iter ( field_patterns. drain ( ..LIMIT ) ) ;
545
- field_patterns. push ( parse_quote ! ( ( #( #end, ) * ) ) ) ;
578
+ field_patterns. push ( match syn:: parse ( quote ! { ( #( #end, ) * ) } . into ( ) ) {
579
+ Ok ( o) => o,
580
+ Err ( e) => return e. into_compile_error ( ) . into ( ) ,
581
+ } ) ;
582
+ }
583
+
584
+ // Create a where clause for the `ReadOnlySystemParam` impl.
585
+ // Ensure that each field implements `ReadOnlySystemParam`.
586
+ let mut read_only_generics = generics. clone ( ) ;
587
+ let read_only_where_clause = read_only_generics. make_where_clause ( ) ;
588
+ for field_type in & field_types {
589
+ read_only_where_clause
590
+ . predicates
591
+ . push ( match syn:: parse ( quote ! { #field_type: #bevy_ecs:: system:: ReadOnlySystemParam } . into ( ) ) {
592
+ Ok ( o) => o,
593
+ Err ( e) => return e. into_compile_error ( ) . into ( ) ,
594
+ } ) ;
546
595
}
547
596
548
597
let struct_name = & ast. ident ;
@@ -556,10 +605,9 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
556
605
} ;
557
606
558
607
let ( system_param, get_param_return, get_param_output) = match fallibility {
559
- SystemParamUsage :: Infallible => ( quote ! { #bevy_ecs:: system:: SystemParam } , quote ! { Self :: Item <' w2, ' s2> } , quote ! { #get_param_output } ) ,
560
- SystemParamUsage :: Optional => ( quote ! { #bevy_ecs:: system:: OptionalSystemParam } , quote ! { Option <Self :: Item <' w2, ' s2>> } , quote ! { Some ( #get_param_output) } ) ,
561
- SystemParamUsage :: Resultful ( _) => ( quote ! { #bevy_ecs:: system:: ResultfulSystemParam } , quote ! { Result <Self :: Item <' w2, ' s2>, <Self :: Item <' w2, ' s2> as #bevy_ecs:: system:: ResultfulSystemParam >:: Error > } , quote ! { Ok ( #get_param_output) } ) ,
562
- SystemParamUsage :: Ignore => unreachable ! ( ) ,
608
+ SystemParamStructUsage :: Infallible => ( quote ! { #bevy_ecs:: system:: SystemParam } , quote ! { Self :: Item <' w2, ' s2> } , quote ! { #get_param_output } ) ,
609
+ SystemParamStructUsage :: Optional => ( quote ! { #bevy_ecs:: system:: OptionalSystemParam } , quote ! { Option <Self :: Item <' w2, ' s2>> } , quote ! { Some ( #get_param_output) } ) ,
610
+ SystemParamStructUsage :: Resultful ( _) => ( quote ! { #bevy_ecs:: system:: ResultfulSystemParam } , quote ! { Result <Self :: Item <' w2, ' s2>, <Self :: Item <' w2, ' s2> as #bevy_ecs:: system:: ResultfulSystemParam >:: Error > } , quote ! { Ok ( #get_param_output) } ) ,
563
611
} ;
564
612
565
613
TokenStream :: from ( quote ! {
@@ -569,7 +617,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
569
617
const _: ( ) = {
570
618
#[ doc( hidden) ]
571
619
#state_struct_visibility struct FetchState <' w, ' s, #( #lifetimeless_generics, ) * > {
572
- state: ( #( <#field_wrapped_types as #bevy_ecs:: system:: SystemParam >:: State , ) * ) ,
620
+ state: ( #( <#field_types as #bevy_ecs:: system:: SystemParam >:: State , ) * ) ,
573
621
marker: std:: marker:: PhantomData <(
574
622
<#bevy_ecs:: prelude:: Query <' w, ' s, ( ) > as #bevy_ecs:: system:: SystemParam >:: State ,
575
623
#( fn ( ) -> #ignored_field_types, ) *
@@ -583,17 +631,17 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
583
631
584
632
fn init_state( world: & mut #bevy_ecs:: world:: World , system_meta: & mut #bevy_ecs:: system:: SystemMeta ) -> Self :: State {
585
633
FetchState {
586
- state: <( #( #field_wrapped_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: init_state( world, system_meta) ,
634
+ state: <( #( #field_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: init_state( world, system_meta) ,
587
635
marker: std:: marker:: PhantomData ,
588
636
}
589
637
}
590
638
591
639
fn new_archetype( state: & mut Self :: State , archetype: & #bevy_ecs:: archetype:: Archetype , system_meta: & mut #bevy_ecs:: system:: SystemMeta ) {
592
- <( #( #field_wrapped_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: new_archetype( & mut state. state, archetype, system_meta)
640
+ <( #( #field_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: new_archetype( & mut state. state, archetype, system_meta)
593
641
}
594
642
595
643
fn apply( state: & mut Self :: State , system_meta: & #bevy_ecs:: system:: SystemMeta , world: & mut #bevy_ecs:: world:: World ) {
596
- <( #( #field_wrapped_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: apply( & mut state. state, system_meta, world) ;
644
+ <( #( #field_types , ) * ) as #bevy_ecs:: system:: SystemParam >:: apply( & mut state. state, system_meta, world) ;
597
645
}
598
646
599
647
unsafe fn get_param<' w2, ' s2>(
@@ -603,7 +651,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
603
651
change_tick: u32 ,
604
652
) -> #get_param_return {
605
653
let ( #( #field_patterns, ) * ) = <
606
- ( #( #field_wrapped_types , ) * ) as #bevy_ecs:: system:: SystemParam
654
+ ( #( #field_types , ) * ) as #bevy_ecs:: system:: SystemParam
607
655
>:: get_param( & mut state. state, system_meta, world, change_tick) ;
608
656
#get_param_output
609
657
}
0 commit comments