@@ -925,24 +925,30 @@ impl World {
925
925
// the ptr value / drop is called when T is dropped
926
926
unsafe { column. swap_remove_and_forget_unchecked ( 0 ) }
927
927
} ;
928
- // SAFE: pointer is of type T
929
- let value = Mut {
930
- value : unsafe { & mut * ptr. cast :: < T > ( ) } ,
928
+ // SAFE: pointer is of type T and valid to move out of
929
+ // Read the value onto the stack to avoid potential mut aliasing.
930
+ let mut value = unsafe { std:: ptr:: read ( ptr. cast :: < T > ( ) ) } ;
931
+ let value_mut = Mut {
932
+ value : & mut value,
931
933
ticks : Ticks {
932
934
component_ticks : & mut ticks,
933
935
last_change_tick : self . last_change_tick ( ) ,
934
936
change_tick : self . change_tick ( ) ,
935
937
} ,
936
938
} ;
937
- let result = f ( self , value) ;
939
+ let result = f ( self , value_mut) ;
940
+ assert ! ( !self . contains_resource:: <T >( ) ) ;
938
941
let resource_archetype = self . archetypes . resource_mut ( ) ;
939
942
let unique_components = resource_archetype. unique_components_mut ( ) ;
940
943
let column = unique_components
941
944
. get_mut ( component_id)
942
945
. unwrap_or_else ( || panic ! ( "resource does not exist: {}" , std:: any:: type_name:: <T >( ) ) ) ;
946
+
947
+ // Wrap the value in MaybeUninit to prepare for passing the value back into the ECS
948
+ let mut nodrop_wrapped_value = std:: mem:: MaybeUninit :: new ( value) ;
943
949
unsafe {
944
- // SAFE: pointer is of type T
945
- column. push ( ptr , ticks) ;
950
+ // SAFE: pointer is of type T, and valid to move out of
951
+ column. push ( nodrop_wrapped_value . as_mut_ptr ( ) as * mut _ , ticks) ;
946
952
}
947
953
result
948
954
}
0 commit comments