@@ -5,7 +5,7 @@ use crate::{
5
5
component:: Component ,
6
6
entity:: { Entity , EntityMap , MapEntities , MapEntitiesError } ,
7
7
system:: Resource ,
8
- world:: { FromWorld , World } ,
8
+ world:: { interior_mutable_world :: InteriorMutableWorld , FromWorld , World } ,
9
9
} ;
10
10
use bevy_reflect:: {
11
11
impl_from_reflect_value, impl_reflect_value, FromType , Reflect , ReflectDeserialize ,
@@ -52,7 +52,8 @@ pub struct ReflectComponentFns {
52
52
/// Function pointer implementing [`ReflectComponent::reflect()`].
53
53
pub reflect : fn ( & World , Entity ) -> Option < & dyn Reflect > ,
54
54
/// Function pointer implementing [`ReflectComponent::reflect_mut()`].
55
- pub reflect_mut : unsafe fn ( & World , Entity ) -> Option < Mut < dyn Reflect > > ,
55
+ /// The function may only be called with a InteriorMutableWorld that can be used to access the relevant component on the given entity
56
+ pub reflect_mut : unsafe fn ( InteriorMutableWorld < ' _ > , Entity ) -> Option < Mut < ' _ , dyn Reflect > > ,
56
57
/// Function pointer implementing [`ReflectComponent::copy()`].
57
58
pub copy : fn ( & World , & mut World , Entity , Entity ) ,
58
59
}
@@ -117,20 +118,20 @@ impl ReflectComponent {
117
118
entity : Entity ,
118
119
) -> Option < Mut < ' a , dyn Reflect > > {
119
120
// SAFETY: unique world access
120
- unsafe { ( self . 0 . reflect_mut ) ( world, entity) }
121
+ unsafe { ( self . 0 . reflect_mut ) ( world. as_interior_mutable ( ) , entity) }
121
122
}
122
123
123
124
/// # Safety
124
125
/// This method does not prevent you from having two mutable pointers to the same data,
125
126
/// violating Rust's aliasing rules. To avoid this:
126
- /// * Only call this method in an exclusive system to avoid sharing across threads (or use a
127
- /// scheduler that enforces safe memory access).
127
+ /// * Only call this method with a [`InteriorMutableWorld`] that may be used to access the component on the entity `entity`
128
128
/// * Don't call this method more than once in the same scope for a given [`Component`].
129
129
pub unsafe fn reflect_unchecked_mut < ' a > (
130
130
& self ,
131
- world : & ' a World ,
131
+ world : InteriorMutableWorld < ' a > ,
132
132
entity : Entity ,
133
133
) -> Option < Mut < ' a , dyn Reflect > > {
134
+ // SAFETY: safety requirements deferred to caller
134
135
( self . 0 . reflect_mut ) ( world, entity)
135
136
}
136
137
@@ -212,6 +213,9 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
212
213
// SAFETY: reflect_mut is an unsafe function pointer used by `reflect_unchecked_mut` which promises to never
213
214
// produce aliasing mutable references, and reflect_mut, which has mutable world access
214
215
unsafe {
216
+ // SAFETY: entity access through the InteriorMutableWorld is not implemented yet.
217
+ // The following code only accesses the component `C` through the entity `entity`
218
+ let world = world. world ( ) ;
215
219
world
216
220
. get_entity ( entity) ?
217
221
. get_unchecked_mut :: < C > ( world. last_change_tick ( ) , world. read_change_tick ( ) )
@@ -265,7 +269,7 @@ pub struct ReflectResourceFns {
265
269
/// Function pointer implementing [`ReflectResource::reflect()`].
266
270
pub reflect : fn ( & World ) -> Option < & dyn Reflect > ,
267
271
/// Function pointer implementing [`ReflectResource::reflect_unchecked_mut()`].
268
- pub reflect_unchecked_mut : unsafe fn ( & World ) -> Option < Mut < dyn Reflect > > ,
272
+ pub reflect_unchecked_mut : unsafe fn ( InteriorMutableWorld < ' _ > ) -> Option < Mut < ' _ , dyn Reflect > > ,
269
273
/// Function pointer implementing [`ReflectResource::copy()`].
270
274
pub copy : fn ( & World , & mut World ) ,
271
275
}
@@ -314,19 +318,18 @@ impl ReflectResource {
314
318
/// Gets the value of this [`Resource`] type from the world as a mutable reflected reference.
315
319
pub fn reflect_mut < ' a > ( & self , world : & ' a mut World ) -> Option < Mut < ' a , dyn Reflect > > {
316
320
// SAFETY: unique world access
317
- unsafe { ( self . 0 . reflect_unchecked_mut ) ( world) }
321
+ unsafe { ( self . 0 . reflect_unchecked_mut ) ( world. as_interior_mutable ( ) ) }
318
322
}
319
323
320
324
/// # Safety
321
325
/// This method does not prevent you from having two mutable pointers to the same data,
322
326
/// violating Rust's aliasing rules. To avoid this:
323
- /// * Only call this method in an exclusive system to avoid sharing across threads (or use a
324
- /// scheduler that enforces safe memory access).
327
+ /// * Only call this method with a [`InteriorMutableWorld`] which can be used to access the resource.
325
328
/// * Don't call this method more than once in the same scope for a given [`Resource`].
326
- pub unsafe fn reflect_unchecked_mut < ' a > (
329
+ pub unsafe fn reflect_unchecked_mut < ' w > (
327
330
& self ,
328
- world : & ' a World ,
329
- ) -> Option < Mut < ' a , dyn Reflect > > {
331
+ world : InteriorMutableWorld < ' w > ,
332
+ ) -> Option < Mut < ' w , dyn Reflect > > {
330
333
// SAFETY: caller promises to uphold uniqueness guarantees
331
334
( self . 0 . reflect_unchecked_mut ) ( world)
332
335
}
@@ -385,13 +388,10 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource {
385
388
// SAFETY: all usages of `reflect_unchecked_mut` guarantee that there is either a single mutable
386
389
// reference or multiple immutable ones alive at any given point
387
390
unsafe {
388
- world
389
- . as_interior_mutable ( )
390
- . get_resource_mut :: < C > ( )
391
- . map ( |res| Mut {
392
- value : res. value as & mut dyn Reflect ,
393
- ticks : res. ticks ,
394
- } )
391
+ world. get_resource_mut :: < C > ( ) . map ( |res| Mut {
392
+ value : res. value as & mut dyn Reflect ,
393
+ ticks : res. ticks ,
394
+ } )
395
395
}
396
396
} ,
397
397
copy : |source_world, destination_world| {
0 commit comments