mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 05:03:47 +00:00
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)]`.
This commit is contained in:
parent
fa2b5f2b36
commit
0d98327ce7
2 changed files with 29 additions and 6 deletions
|
@ -14,8 +14,8 @@ use syn::{
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
spanned::Spanned,
|
spanned::Spanned,
|
||||||
token::Comma,
|
token::Comma,
|
||||||
DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta, Result,
|
ConstParam, DeriveInput, Field, GenericParam, Ident, Index, LitInt, Meta, MetaList, NestedMeta,
|
||||||
Token, TypeParam,
|
Result, Token, TypeParam,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AllTuples {
|
struct AllTuples {
|
||||||
|
@ -416,7 +416,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
||||||
let lifetimeless_generics: Vec<_> = generics
|
let lifetimeless_generics: Vec<_> = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| matches!(g, GenericParam::Type(_)))
|
.filter(|g| !matches!(g, GenericParam::Lifetime(_)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
|
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
|
||||||
|
@ -425,12 +425,32 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
||||||
default: None,
|
default: None,
|
||||||
..g.clone()
|
..g.clone()
|
||||||
}),
|
}),
|
||||||
|
GenericParam::Const(g) => GenericParam::Const(ConstParam {
|
||||||
|
default: None,
|
||||||
|
..g.clone()
|
||||||
|
}),
|
||||||
_ => unreachable!(),
|
_ => 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();
|
let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
|
||||||
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
|
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
|
||||||
GenericParam::Type(g) => &g.ident,
|
GenericParam::Type(g) => &g.ident,
|
||||||
|
GenericParam::Const(g) => &g.ident,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -470,15 +490,15 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[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,)*),
|
(#(<#tuple_types as #path::system::SystemParam>::State,)*),
|
||||||
#punctuated_generic_idents
|
#punctuated_generic_idents
|
||||||
>;
|
>;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generic_idents> {
|
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generics> {
|
||||||
state: TSystemParamState,
|
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
|
unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for
|
||||||
|
|
|
@ -1772,6 +1772,9 @@ mod tests {
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct R<const I: usize>;
|
pub struct R<const I: usize>;
|
||||||
|
|
||||||
|
#[derive(SystemParam)]
|
||||||
|
pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
|
||||||
|
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct LongParam<'w> {
|
pub struct LongParam<'w> {
|
||||||
_r0: Res<'w, R<0>>,
|
_r0: Res<'w, R<0>>,
|
||||||
|
|
Loading…
Reference in a new issue