@@ -1256,19 +1256,57 @@ pub mod lifetimeless {
12561256
12571257/// A helper for using system parameters in generic contexts
12581258///
1259- /// This type is a system parameter which is statically proven to have
1260- /// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity)
1259+ /// This type is a [`SystemParam`] adapter which always has
1260+ /// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity),
1261+ /// no matter the argument [`SystemParam`] (`P`) (other than
1262+ /// that `P` must be `'static`)
1263+ ///
1264+ /// This makes it useful for having arbitrary [`SystemParam`] type arguments
1265+ /// to function systems, or for generic types using the [`derive@SystemParam`]
1266+ /// derive:
12611267///
12621268/// ```
12631269/// # use bevy_ecs::prelude::*;
12641270/// use bevy_ecs::system::{SystemParam, StaticSystemParam};
1265- ///
1271+ /// #[derive(SystemParam)]
1272+ /// struct GenericParam<'w,'s, T: SystemParam + 'static> {
1273+ /// field: StaticSystemParam<'w, 's, T>,
1274+ /// }
12661275/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}
12671276///
1268- /// fn test_always_is <T: SystemParam + 'static>(){
1277+ /// fn check_always_is_system <T: SystemParam + 'static>(){
12691278/// do_thing_generically::<T>.system();
12701279/// }
12711280/// ```
1281+ /// Note that in a real case you'd generally want
1282+ /// additional bounds on `P`, for your use of the parameter
1283+ /// to have a reason to be generic.
1284+ ///
1285+ /// For example, using this would allow a type to be generic over
1286+ /// whether a resource is accessed mutably or not, with
1287+ /// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and
1288+ /// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the
1289+ /// method requires mutable access or not.
1290+ ///
1291+ /// The method which doesn't use this type will not compile:
1292+ /// ```compile_fail
1293+ /// # use bevy_ecs::prelude::*;
1294+ /// # use bevy_ecs::system::{SystemParam, StaticSystemParam};
1295+ ///
1296+ /// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
1297+ ///
1298+ /// #[derive(SystemParam)]
1299+ /// struct GenericParam<'w,'s, T: SystemParam> {
1300+ /// field: T,
1301+ /// #[system_param(ignore)]
1302+ /// // Use the lifetimes, as the `SystemParam` derive requires them
1303+ /// phantom: core::marker::PhantomData<&'w &'s ()>
1304+ /// }
1305+ /// # fn check_always_is_system<T: SystemParam + 'static>(){
1306+ /// # do_thing_generically::<T>.system();
1307+ /// # }
1308+ /// ```
1309+ ///
12721310pub struct StaticSystemParam < ' w , ' s , P : SystemParam > ( SystemParamItem < ' w , ' s , P > ) ;
12731311
12741312impl < ' w , ' s , P : SystemParam > Deref for StaticSystemParam < ' w , ' s , P > {
@@ -1286,13 +1324,21 @@ impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
12861324}
12871325
12881326impl < ' w , ' s , P : SystemParam > StaticSystemParam < ' w , ' s , P > {
1289- pub fn inner ( self ) -> SystemParamItem < ' w , ' s , P > {
1327+ /// Get the value of the parameter
1328+ pub fn into_inner ( self ) -> SystemParamItem < ' w , ' s , P > {
12901329 self . 0
12911330 }
12921331}
12931332
1333+ /// The [`SystemParamState`] of [`SystemChangeTick`].
12941334pub struct StaticSystemParamState < S , P > ( S , PhantomData < fn ( ) -> P > ) ;
12951335
1336+ // Safe: This doesn't add any more reads, and the delegated fetch confirms it
1337+ unsafe impl < ' w , ' s , S : ReadOnlySystemParamFetch , P > ReadOnlySystemParamFetch
1338+ for StaticSystemParamState < S , P >
1339+ {
1340+ }
1341+
12961342impl < ' world , ' state , P : SystemParam + ' static > SystemParam
12971343 for StaticSystemParam < ' world , ' state , P >
12981344{
@@ -1312,6 +1358,7 @@ where
13121358 world : & ' world World ,
13131359 change_tick : u32 ,
13141360 ) -> Self :: Item {
1361+ // Safe: We properly delegate SystemParamState
13151362 StaticSystemParam ( S :: get_param ( & mut state. 0 , system_meta, world, change_tick) )
13161363 }
13171364}
0 commit comments