[Merged by Bors] - Simplify trait hierarchy for SystemParam#6865
[Merged by Bors] - Simplify trait hierarchy for SystemParam#6865joseph-gio wants to merge 20 commits intobevyengine:mainfrom
SystemParam#6865Conversation
|
Could we go one step further, as we have with |
|
Unfortunately that is not possible due to how GATs work for now. You are forced to add the |
Nevermind, I misunderstood how required bounds work the first time I tried this. Working on some more improvements. |
alice-i-cecile
left a comment
There was a problem hiding this comment.
This change results in a serious simplification, and appears to be correctly done. @BoxyUwU can you double check this?
|
My ultimate goal is to merge It seems doable, but unfortunately there is a nightmare of trait bounds that may take a while to untangle. It will also have hundreds of additional lines of churn, so I think I will split it off into a future PR. |
|
One last change: I replaced |
|
@JoJoJet If you are planning to merge Basically, I want to make both generic for I don't think this would have any significant effect on your implementation. I'm guessing you just want to make it so |
@JonahPlusPlus There's still a few things left to figure out for that PR, so it's not a sure thing for it to get merged. I wouldn't wait, so long as you're okay with a little rebasing if needed. |
| // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. | ||
| unsafe impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> ReadOnlySystemParam | ||
| for Query<'w, 's, Q, F> | ||
| unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> |
There was a problem hiding this comment.
Was this required by the compiler? This seems incorrect to me.
There was a problem hiding this comment.
These bounds are required because ReadOnlySystemParam: SystemParam -- same reason I had to add them to StaticSystemParam before. The bounds already exist on impl SystemParam for Query<>, so nothing is lost here.
There was a problem hiding this comment.
oh awesome I didn't realise we were already requiring Q: 'static and F: 'static on the SystemParam impl. We should just require trait WorldQuery: 'static then
There was a problem hiding this comment.
Oh man that's nutty. Seems counterintuitive in this case, though probably for the best. LGTM then, we can address the WorldQuery: 'static thing in another PR.
There was a problem hiding this comment.
We should just require trait WorldQuery: 'static then
I agree -- I just tried this though and it seems like it'll add a bunch of churn, so I'll leave it for another PR.
| /// [`World`] access used by the [`SystemParamState`]. | ||
| /// Additionally, it is the implementor's responsibility to ensure there is no | ||
| /// conflicting access across all [`SystemParam`]'s. | ||
| pub unsafe trait SystemParamState: Send + Sync + 'static { |
There was a problem hiding this comment.
Does this and the function get_param have to both be marked unsafe?
There was a problem hiding this comment.
Yes. unsafe has different implications for fns and traits: unsafe fn requires the caller of the fn to uphold safety invariants, whereas unsafe trait requires the implementer of the trait to uphold safety invariants. In this case, we want it to be both unsafe to implement and to call, so we mark both as unsafe.
There was a problem hiding this comment.
Ah, so the other methods are unsafe to implement, but get_param is unsafe to call. Thanks for the clarification, I couldn't find anything online explaining why you would prefer one over the other.
|
bors r+ |
# Objective
* Implementing a custom `SystemParam` by hand requires implementing three traits -- four if it is read-only.
* The trait `SystemParamFetch<'w, 's>` is a workaround from before we had generic associated types, and is no longer necessary.
## Solution
* Combine the trait `SystemParamFetch` with `SystemParamState`.
* I decided to remove the `Fetch` name and keep the `State` name, since the former was consistently conflated with the latter.
* Replace the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`, which simplifies trait bounds in generic code.
---
## Changelog
- Removed the trait `SystemParamFetch`, moving its functionality to `SystemParamState`.
- Replaced the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`.
## Migration Guide
The trait `SystemParamFetch` has been removed, and its functionality has been transferred to `SystemParamState`.
```rust
// Before
impl SystemParamState for MyParamState {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
type Item = MyParam<'w, 's>;
fn get_param(...) -> Self::Item;
}
// After
impl SystemParamState for MyParamState {
type Item<'w, 's> = MyParam<'w, 's>; // Generic associated types!
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
fn get_param<'w, 's>(...) -> Self::Item<'w, 's>;
}
```
The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`.
```rust
// Before
unsafe impl ReadOnlySystemParamFetch for MyParamState {}
// After
unsafe impl<'w, 's> ReadOnlySystemParam for MyParam<'w, 's> {}
```
SystemParamSystemParam
…6919) Spiritual successor to #5205. Actual successor to #6865. # Objective Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state. Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it. ## Solution * Merge the trait `SystemParamState` into `SystemParam`. * Remove all trivial `SystemParam` state types. * `OptionNonSendMutState<T>`: you will not be missed. --- - [x] Fix/resolve the remaining test failure. ## Changelog * Removed the trait `SystemParamState`, merging its functionality into `SystemParam`. ## Migration Guide **Note**: this should replace the migration guide for #6865. This is relative to Bevy 0.9, not main. The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. ```rust // Before (0.9) impl SystemParam for MyParam<'_, '_> { type State = MyParamState; } unsafe impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(&mut self, ...) -> Self::Item; } unsafe impl ReadOnlySystemParamFetch for MyParamState { } // After (0.10) unsafe impl SystemParam for MyParam<'_, '_> { type State = MyParamState; type Item<'w, 's> = MyParam<'w, 's>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; } unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {} ```
…evyengine#6919) Spiritual successor to bevyengine#5205. Actual successor to bevyengine#6865. # Objective Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state. Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it. ## Solution * Merge the trait `SystemParamState` into `SystemParam`. * Remove all trivial `SystemParam` state types. * `OptionNonSendMutState<T>`: you will not be missed. --- - [x] Fix/resolve the remaining test failure. ## Changelog * Removed the trait `SystemParamState`, merging its functionality into `SystemParam`. ## Migration Guide **Note**: this should replace the migration guide for bevyengine#6865. This is relative to Bevy 0.9, not main. The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. ```rust // Before (0.9) impl SystemParam for MyParam<'_, '_> { type State = MyParamState; } unsafe impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(&mut self, ...) -> Self::Item; } unsafe impl ReadOnlySystemParamFetch for MyParamState { } // After (0.10) unsafe impl SystemParam for MyParam<'_, '_> { type State = MyParamState; type Item<'w, 's> = MyParam<'w, 's>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; } unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {} ```
# Objective
* Implementing a custom `SystemParam` by hand requires implementing three traits -- four if it is read-only.
* The trait `SystemParamFetch<'w, 's>` is a workaround from before we had generic associated types, and is no longer necessary.
## Solution
* Combine the trait `SystemParamFetch` with `SystemParamState`.
* I decided to remove the `Fetch` name and keep the `State` name, since the former was consistently conflated with the latter.
* Replace the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`, which simplifies trait bounds in generic code.
---
## Changelog
- Removed the trait `SystemParamFetch`, moving its functionality to `SystemParamState`.
- Replaced the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`.
## Migration Guide
The trait `SystemParamFetch` has been removed, and its functionality has been transferred to `SystemParamState`.
```rust
// Before
impl SystemParamState for MyParamState {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
type Item = MyParam<'w, 's>;
fn get_param(...) -> Self::Item;
}
// After
impl SystemParamState for MyParamState {
type Item<'w, 's> = MyParam<'w, 's>; // Generic associated types!
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
fn get_param<'w, 's>(...) -> Self::Item<'w, 's>;
}
```
The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`.
```rust
// Before
unsafe impl ReadOnlySystemParamFetch for MyParamState {}
// After
unsafe impl<'w, 's> ReadOnlySystemParam for MyParam<'w, 's> {}
```
…evyengine#6919) Spiritual successor to bevyengine#5205. Actual successor to bevyengine#6865. # Objective Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state. Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it. ## Solution * Merge the trait `SystemParamState` into `SystemParam`. * Remove all trivial `SystemParam` state types. * `OptionNonSendMutState<T>`: you will not be missed. --- - [x] Fix/resolve the remaining test failure. ## Changelog * Removed the trait `SystemParamState`, merging its functionality into `SystemParam`. ## Migration Guide **Note**: this should replace the migration guide for bevyengine#6865. This is relative to Bevy 0.9, not main. The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. ```rust // Before (0.9) impl SystemParam for MyParam<'_, '_> { type State = MyParamState; } unsafe impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(&mut self, ...) -> Self::Item; } unsafe impl ReadOnlySystemParamFetch for MyParamState { } // After (0.10) unsafe impl SystemParam for MyParam<'_, '_> { type State = MyParamState; type Item<'w, 's> = MyParam<'w, 's>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; } unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {} ```
# Objective
* Implementing a custom `SystemParam` by hand requires implementing three traits -- four if it is read-only.
* The trait `SystemParamFetch<'w, 's>` is a workaround from before we had generic associated types, and is no longer necessary.
## Solution
* Combine the trait `SystemParamFetch` with `SystemParamState`.
* I decided to remove the `Fetch` name and keep the `State` name, since the former was consistently conflated with the latter.
* Replace the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`, which simplifies trait bounds in generic code.
---
## Changelog
- Removed the trait `SystemParamFetch`, moving its functionality to `SystemParamState`.
- Replaced the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`.
## Migration Guide
The trait `SystemParamFetch` has been removed, and its functionality has been transferred to `SystemParamState`.
```rust
// Before
impl SystemParamState for MyParamState {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
type Item = MyParam<'w, 's>;
fn get_param(...) -> Self::Item;
}
// After
impl SystemParamState for MyParamState {
type Item<'w, 's> = MyParam<'w, 's>; // Generic associated types!
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
fn get_param<'w, 's>(...) -> Self::Item<'w, 's>;
}
```
The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`.
```rust
// Before
unsafe impl ReadOnlySystemParamFetch for MyParamState {}
// After
unsafe impl<'w, 's> ReadOnlySystemParam for MyParam<'w, 's> {}
```
…evyengine#6919) Spiritual successor to bevyengine#5205. Actual successor to bevyengine#6865. # Objective Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state. Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it. ## Solution * Merge the trait `SystemParamState` into `SystemParam`. * Remove all trivial `SystemParam` state types. * `OptionNonSendMutState<T>`: you will not be missed. --- - [x] Fix/resolve the remaining test failure. ## Changelog * Removed the trait `SystemParamState`, merging its functionality into `SystemParam`. ## Migration Guide **Note**: this should replace the migration guide for bevyengine#6865. This is relative to Bevy 0.9, not main. The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. ```rust // Before (0.9) impl SystemParam for MyParam<'_, '_> { type State = MyParamState; } unsafe impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(&mut self, ...) -> Self::Item; } unsafe impl ReadOnlySystemParamFetch for MyParamState { } // After (0.10) unsafe impl SystemParam for MyParam<'_, '_> { type State = MyParamState; type Item<'w, 's> = MyParam<'w, 's>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; } unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {} ```
Objective
SystemParamby hand requires implementing three traits -- four if it is read-only.SystemParamFetch<'w, 's>is a workaround from before we had generic associated types, and is no longer necessary.Solution
SystemParamFetchwithSystemParamState.Fetchname and keep theStatename, since the former was consistently conflated with the latter.ReadOnlySystemParamFetchwithReadOnlySystemParam, which simplifies trait bounds in generic code.Changelog
SystemParamFetch, moving its functionality toSystemParamState.ReadOnlySystemParamFetchwithReadOnlySystemParam.Migration Guide
Merged with the guide for #6919.