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