Allow to mutably query for immutable components
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
Related https://github.com/bevyengine/bevy/pull/17140
Often you want to lock end users from mutating component, while still having the ability to mutate it in the library internals. For example there is a Child and Parent relationship in the bevy_hierarchy https://github.com/bevyengine/bevy/pull/16662
Currently, this access only limited to the exclusive world access. Querying also can be an option
## What solution would you like?
There are two ways of implementing it:
Add new smart pointer analogue to `Mut` that implements `QueryData` and only allows getting mutable access via unsafe methods
```rust
impl<'a, T> AssumeMut<'a, T> {
/// - One of the following should be true:
/// - Either `T` is mutable, or
/// - `OnReplace` hooks and observers for that component on that entity should trigger immediately before the mutation
/// and `OnInsert` should trigger immediately after the mutation, or
/// - The user should uphold documented invariants of `T`. If no such documentation provided, it is impossible for the end user to uphold this.
unsafe fn assume_mut(self) -> Mut<'a, T> {
// ....
}
}
```
Or
Change `Mut` smart pointer in a way to add `assume_mut` function if the type it points to is immutable.
```rust
impl Mut<'_, T> {
/// - One of the following should be true:
/// - Either `T` is mutable, or
/// - `OnReplace` hooks and observers for that component on that entity should trigger immediately before the mutation
/// and `OnInsert` should trigger immediately after the mutation, or
/// - The user should uphold documented invariants of `T`. If no such documentation provided, it is impossible for the end user to uphold this.
unsafe fn assume_mut(&mut self) -> &mut T {
// ....
}
}
```
For that current implementation of immutable components does not work, since `Mut` is generic over any type, but `DerefMut` only should be implemented for mutable components. For that we can either
```rust
trait Mutable {}
impl DerefMut for Mut<'_, T> { /*..*/ }
```
Or
```rust
trait Mutability {
type Mutability: ComponentMutability; // Rename would be desired
}
trait Component: Mutability {
// No associated `Mutability` type
//...
}
impl> DerefMut for Mut<'_, T> { /*...*/ }
```
Contributor guide
Assessment
This issue has not been assessed yet.