Make derived SystemParam readonly if possible (#4650)
Required for https://github.com/bevyengine/bevy/pull/4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
This commit is contained in:
parent
4c878ef790
commit
38a940dbbe
@ -324,7 +324,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.expect("Invalid 'render_resources' attribute format.");
|
.expect("Invalid 'system_param' attribute format.");
|
||||||
|
|
||||||
attributes
|
attributes
|
||||||
}),
|
}),
|
||||||
@ -420,6 +420,9 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety: The `ParamState` is `ReadOnlySystemParamFetch`, so this can only read from the `World`
|
||||||
|
unsafe impl<TSystemParamState: #path::system::SystemParamState + #path::system::ReadOnlySystemParamFetch, #punctuated_generics> #path::system::ReadOnlySystemParamFetch for FetchState <TSystemParamState, #punctuated_generic_idents> #where_clause {}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -513,6 +513,8 @@ impl<E: Event> std::iter::Extend<E> for Events<E> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::{prelude::World, system::SystemState};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
@ -753,4 +755,16 @@ mod tests {
|
|||||||
vec![EmptyTestEvent::default()]
|
vec![EmptyTestEvent::default()]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ensure_reader_readonly() {
|
||||||
|
fn read_for<E: Event>() {
|
||||||
|
let mut world = World::new();
|
||||||
|
world.init_resource::<Events<E>>();
|
||||||
|
let mut state = SystemState::<EventReader<E>>::new(&mut world);
|
||||||
|
// This can only work if EventReader only reads the world
|
||||||
|
let _reader = state.get(&world);
|
||||||
|
}
|
||||||
|
read_for::<EmptyTestEvent>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
#[derive(SystemParam)]
|
||||||
|
struct Mutable<'w, 's> {
|
||||||
|
a: Query<'w, 's, &'static mut Foo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Ideally we'd use:
|
||||||
|
// let mut world = World::default();
|
||||||
|
// let state = SystemState::<Mutable>::new(&mut world);
|
||||||
|
// state.get(&world);
|
||||||
|
// But that makes the test show absolute paths
|
||||||
|
assert_readonly::<Mutable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_readonly<P: SystemParam>()
|
||||||
|
where
|
||||||
|
<P as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
warning: unused import: `SystemState`
|
||||||
|
--> tests/ui/system_param_derive_readonly.rs:2:63
|
||||||
|
|
|
||||||
|
2 | use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `for<'x> WriteFetch<'x, Foo>: ReadOnlyFetch` is not satisfied
|
||||||
|
--> tests/ui/system_param_derive_readonly.rs:18:5
|
||||||
|
|
|
||||||
|
18 | assert_readonly::<Mutable>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'x> ReadOnlyFetch` is not implemented for `WriteFetch<'x, Foo>`
|
||||||
|
|
|
||||||
|
= note: required because of the requirements on the impl of `ReadOnlySystemParamFetch` for `QueryState<&'static mut Foo>`
|
||||||
|
= note: 2 redundant requirements hidden
|
||||||
|
= note: required because of the requirements on the impl of `ReadOnlySystemParamFetch` for `_::FetchState<(QueryState<&'static mut Foo>,)>`
|
||||||
|
note: required by a bound in `assert_readonly`
|
||||||
|
--> tests/ui/system_param_derive_readonly.rs:23:32
|
||||||
|
|
|
||||||
|
21 | fn assert_readonly<P: SystemParam>()
|
||||||
|
| --------------- required by a bound in this
|
||||||
|
22 | where
|
||||||
|
23 | <P as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly`
|
||||||
Loading…
Reference in New Issue
Block a user