Skip to content

Commit

Permalink
Support SystemParam types with const generics (bevyengine#7001)
Browse files Browse the repository at this point in the history
# 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 bevyengine#6867 and bevyengine#6957.

## Solution

Allow const generic parameters to be used with `#[derive(SystemParam)]`.
  • Loading branch information
JoJoJet authored and ItsDoot committed Feb 1, 2023
1 parent 26c57a9 commit ea3a605
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
32 changes: 26 additions & 6 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use syn::{
punctuated::Punctuated,
spanned::Spanned,
token::Comma,
DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta, Result,
Token, TypeParam,
ConstParam, DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta,
Result, Token, TypeParam,
};

struct AllTuples {
Expand Down Expand Up @@ -416,7 +416,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
let lifetimeless_generics: Vec<_> = generics
.params
.iter()
.filter(|g| matches!(g, GenericParam::Type(_)))
.filter(|g| !matches!(g, GenericParam::Lifetime(_)))
.collect();

let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
Expand All @@ -425,12 +425,32 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
default: None,
..g.clone()
}),
GenericParam::Const(g) => GenericParam::Const(ConstParam {
default: None,
..g.clone()
}),
_ => unreachable!(),
}));

let mut punctuated_generics_no_bounds = punctuated_generics.clone();
for g in &mut punctuated_generics_no_bounds {
match g {
GenericParam::Type(g) => g.bounds.clear(),
GenericParam::Lifetime(g) => g.bounds.clear(),
GenericParam::Const(_) => {}
}
}

let mut punctuated_type_generic_idents = Punctuated::<_, Token![,]>::new();
punctuated_type_generic_idents.extend(lifetimeless_generics.iter().filter_map(|g| match g {
GenericParam::Type(g) => Some(&g.ident),
_ => None,
}));

let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
GenericParam::Type(g) => &g.ident,
GenericParam::Const(g) => &g.ident,
_ => unreachable!(),
}));

Expand Down Expand Up @@ -470,15 +490,15 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
}

#[doc(hidden)]
type State<'w, 's, #punctuated_generic_idents> = FetchState<
type State<'w, 's, #punctuated_generics_no_bounds> = FetchState<
(#(<#tuple_types as #path::system::SystemParam>::State,)*),
#punctuated_generic_idents
>;

#[doc(hidden)]
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generic_idents> {
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generics> {
state: TSystemParamState,
marker: std::marker::PhantomData<fn()->(#punctuated_generic_idents)>
marker: std::marker::PhantomData<fn()->(#punctuated_type_generic_idents)>
}

unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,9 @@ mod tests {
#[derive(Resource)]
pub struct R<const I: usize>;

#[derive(SystemParam)]
pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);

#[derive(SystemParam)]
pub struct LongParam<'w> {
_r0: Res<'w, R<0>>,
Expand Down

0 comments on commit ea3a605

Please sign in to comment.