@@ -1332,19 +1332,57 @@ pub mod lifetimeless {
13321332
13331333/// A helper for using system parameters in generic contexts
13341334///
1335- /// This type is a system parameter which is statically proven to have
1336- /// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity)
1335+ /// This type is a [`SystemParam`] adapter which always has
1336+ /// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity),
1337+ /// no matter the argument [`SystemParam`] (`P`) (other than
1338+ /// that `P` must be `'static`)
1339+ ///
1340+ /// This makes it useful for having arbitrary [`SystemParam`] type arguments
1341+ /// to function systems, or for generic types using the [`derive@SystemParam`]
1342+ /// derive:
13371343///
13381344/// ```
13391345/// # use bevy_ecs::prelude::*;
13401346/// use bevy_ecs::system::{SystemParam, StaticSystemParam};
1341- ///
1347+ /// #[derive(SystemParam)]
1348+ /// struct GenericParam<'w,'s, T: SystemParam + 'static> {
1349+ /// field: StaticSystemParam<'w, 's, T>,
1350+ /// }
13421351/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}
13431352///
1344- /// fn test_always_is <T: SystemParam + 'static>(){
1353+ /// fn check_always_is_system <T: SystemParam + 'static>(){
13451354/// do_thing_generically::<T>.system();
13461355/// }
13471356/// ```
1357+ /// Note that in a real case you'd generally want
1358+ /// additional bounds on `P`, for your use of the parameter
1359+ /// to have a reason to be generic.
1360+ ///
1361+ /// For example, using this would allow a type to be generic over
1362+ /// whether a resource is accessed mutably or not, with
1363+ /// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and
1364+ /// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the
1365+ /// method requires mutable access or not.
1366+ ///
1367+ /// The method which doesn't use this type will not compile:
1368+ /// ```compile_fail
1369+ /// # use bevy_ecs::prelude::*;
1370+ /// # use bevy_ecs::system::{SystemParam, StaticSystemParam};
1371+ ///
1372+ /// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
1373+ ///
1374+ /// #[derive(SystemParam)]
1375+ /// struct GenericParam<'w,'s, T: SystemParam> {
1376+ /// field: T,
1377+ /// #[system_param(ignore)]
1378+ /// // Use the lifetimes, as the `SystemParam` derive requires them
1379+ /// phantom: core::marker::PhantomData<&'w &'s ()>
1380+ /// }
1381+ /// # fn check_always_is_system<T: SystemParam + 'static>(){
1382+ /// # do_thing_generically::<T>.system();
1383+ /// # }
1384+ /// ```
1385+ ///
13481386pub struct StaticSystemParam < ' w , ' s , P : SystemParam > ( SystemParamItem < ' w , ' s , P > ) ;
13491387
13501388impl < ' w , ' s , P : SystemParam > Deref for StaticSystemParam < ' w , ' s , P > {
@@ -1362,13 +1400,21 @@ impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
13621400}
13631401
13641402impl < ' w , ' s , P : SystemParam > StaticSystemParam < ' w , ' s , P > {
1365- pub fn inner ( self ) -> SystemParamItem < ' w , ' s , P > {
1403+ /// Get the value of the parameter
1404+ pub fn into_inner ( self ) -> SystemParamItem < ' w , ' s , P > {
13661405 self . 0
13671406 }
13681407}
13691408
1409+ /// The [`SystemParamState`] of [`SystemChangeTick`].
13701410pub struct StaticSystemParamState < S , P > ( S , PhantomData < fn ( ) -> P > ) ;
13711411
1412+ // Safe: This doesn't add any more reads, and the delegated fetch confirms it
1413+ unsafe impl < ' w , ' s , S : ReadOnlySystemParamFetch , P > ReadOnlySystemParamFetch
1414+ for StaticSystemParamState < S , P >
1415+ {
1416+ }
1417+
13721418impl < ' world , ' state , P : SystemParam + ' static > SystemParam
13731419 for StaticSystemParam < ' world , ' state , P >
13741420{
@@ -1388,6 +1434,7 @@ where
13881434 world : & ' world World ,
13891435 change_tick : u32 ,
13901436 ) -> Self :: Item {
1437+ // Safe: We properly delegate SystemParamState
13911438 StaticSystemParam ( S :: get_param ( & mut state. 0 , system_meta, world, change_tick) )
13921439 }
13931440}
0 commit comments