Skip to content

Commit 0d98327

Browse files
committed
Support SystemParam types with const generics (#7001)
# Objective * Currently, the `SystemParam` derive does not support types with const generic parameters. * If you try to use const generics, the error message is cryptic and unhelpful. * Continuation of the work started in #6867 and #6957. ## Solution Allow const generic parameters to be used with `#[derive(SystemParam)]`.
1 parent fa2b5f2 commit 0d98327

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use syn::{
1414
punctuated::Punctuated,
1515
spanned::Spanned,
1616
token::Comma,
17-
DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta, Result,
18-
Token, TypeParam,
17+
ConstParam, DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta,
18+
Result, Token, TypeParam,
1919
};
2020

2121
struct AllTuples {
@@ -416,7 +416,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
416416
let lifetimeless_generics: Vec<_> = generics
417417
.params
418418
.iter()
419-
.filter(|g| matches!(g, GenericParam::Type(_)))
419+
.filter(|g| !matches!(g, GenericParam::Lifetime(_)))
420420
.collect();
421421

422422
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
@@ -425,12 +425,32 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
425425
default: None,
426426
..g.clone()
427427
}),
428+
GenericParam::Const(g) => GenericParam::Const(ConstParam {
429+
default: None,
430+
..g.clone()
431+
}),
428432
_ => unreachable!(),
429433
}));
430434

435+
let mut punctuated_generics_no_bounds = punctuated_generics.clone();
436+
for g in &mut punctuated_generics_no_bounds {
437+
match g {
438+
GenericParam::Type(g) => g.bounds.clear(),
439+
GenericParam::Lifetime(g) => g.bounds.clear(),
440+
GenericParam::Const(_) => {}
441+
}
442+
}
443+
444+
let mut punctuated_type_generic_idents = Punctuated::<_, Token![,]>::new();
445+
punctuated_type_generic_idents.extend(lifetimeless_generics.iter().filter_map(|g| match g {
446+
GenericParam::Type(g) => Some(&g.ident),
447+
_ => None,
448+
}));
449+
431450
let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
432451
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
433452
GenericParam::Type(g) => &g.ident,
453+
GenericParam::Const(g) => &g.ident,
434454
_ => unreachable!(),
435455
}));
436456

@@ -470,15 +490,15 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
470490
}
471491

472492
#[doc(hidden)]
473-
type State<'w, 's, #punctuated_generic_idents> = FetchState<
493+
type State<'w, 's, #punctuated_generics_no_bounds> = FetchState<
474494
(#(<#tuple_types as #path::system::SystemParam>::State,)*),
475495
#punctuated_generic_idents
476496
>;
477497

478498
#[doc(hidden)]
479-
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generic_idents> {
499+
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generics> {
480500
state: TSystemParamState,
481-
marker: std::marker::PhantomData<fn()->(#punctuated_generic_idents)>
501+
marker: std::marker::PhantomData<fn()->(#punctuated_type_generic_idents)>
482502
}
483503

484504
unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,9 @@ mod tests {
17721772
#[derive(Resource)]
17731773
pub struct R<const I: usize>;
17741774

1775+
#[derive(SystemParam)]
1776+
pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
1777+
17751778
#[derive(SystemParam)]
17761779
pub struct LongParam<'w> {
17771780
_r0: Res<'w, R<0>>,

0 commit comments

Comments
 (0)