From 69e9a47d92ff8599c270d77a6ce2917c97059d8c Mon Sep 17 00:00:00 2001 From: MinerSebas Date: Thu, 3 Feb 2022 03:32:02 +0000 Subject: [PATCH] SystemParam Derive fixes (#2838) # Objective A user on Discord couldn't derive SystemParam for this Struct: ```rs #[derive(SystemParam)] pub struct SpatialQuery<'w, 's, Q: WorldQuery + Send + Sync + 'static, F: WorldQuery + Send + Sync + 'static = ()> where F::Fetch: FilterFetch, { query: Query<'w, 's, (C, &'static Transform), F>, } ``` ## Solution 1. The `where`-clause is now also copied to the `SystemParamFetch` impl Block. 2. The `SystemParamState` impl Block no longer gets any defaults for generics Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com> --- crates/bevy_ecs/macros/src/lib.rs | 14 +++++++++---- crates/bevy_ecs/src/system/system_param.rs | 24 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 548f2310a162f..ca5a6b17bff59 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -11,7 +11,7 @@ use syn::{ parse_macro_input, punctuated::Punctuated, token::Comma, - DeriveInput, Field, GenericParam, Ident, Index, LitInt, Result, Token, + DeriveInput, Field, GenericParam, Ident, Index, LitInt, Result, Token, TypeParam, }; struct AllTuples { @@ -357,12 +357,18 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { .collect(); let mut punctuated_generics = Punctuated::<_, Token![,]>::new(); - punctuated_generics.extend(lifetimeless_generics.iter()); + punctuated_generics.extend(lifetimeless_generics.iter().map(|g| match g { + GenericParam::Type(g) => GenericParam::Type(TypeParam { + default: None, + ..g.clone() + }), + _ => unreachable!(), + })); let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new(); punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g { GenericParam::Type(g) => &g.ident, - _ => panic!(), + _ => unreachable!(), })); let struct_name = &ast.ident; @@ -402,7 +408,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { } } - impl #impl_generics #path::system::SystemParamFetch<'w, 's> for #fetch_struct_name <(#(<#field_types as #path::system::SystemParam>::Fetch,)*), #punctuated_generic_idents> { + impl #impl_generics #path::system::SystemParamFetch<'w, 's> for #fetch_struct_name <(#(<#field_types as #path::system::SystemParam>::Fetch,)*), #punctuated_generic_idents> #where_clause { type Item = #struct_name #ty_generics; unsafe fn get_param( state: &'s mut Self, diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index d919f2788052c..56900decf213e 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1253,3 +1253,27 @@ pub mod lifetimeless { pub type SResMut = super::ResMut<'static, T>; pub type SCommands = crate::system::Commands<'static, 'static>; } + +#[cfg(test)] +mod tests { + use super::SystemParam; + use crate::{ + self as bevy_ecs, // Necessary for the `SystemParam` Derive when used inside `bevy_ecs`. + query::{FilterFetch, WorldQuery}, + system::Query, + }; + + // Compile test for #2838 + #[derive(SystemParam)] + pub struct SpecialQuery< + 'w, + 's, + Q: WorldQuery + Send + Sync + 'static, + F: WorldQuery + Send + Sync + 'static = (), + > + where + F::Fetch: FilterFetch, + { + _query: Query<'w, 's, Q, F>, + } +}