File tree Expand file tree Collapse file tree 2 files changed +31
-1
lines changed Expand file tree Collapse file tree 2 files changed +31
-1
lines changed Original file line number Diff line number Diff line change @@ -232,7 +232,12 @@ pub unsafe trait ErasablePtr {
232
232
Self : Sized ,
233
233
F : FnOnce ( & mut Self ) -> T ,
234
234
{
235
- f ( & mut ManuallyDrop :: new ( & mut Self :: unerase ( * this) ) )
235
+ // SAFETY: guard is required to write potentially changed pointer value, even on unwind
236
+ let mut that = scopeguard:: guard ( ManuallyDrop :: new ( Self :: unerase ( * this) ) , |unerased| {
237
+ ptr:: write ( this, ErasablePtr :: erase ( ManuallyDrop :: into_inner ( unerased) ) ) ;
238
+ } ) ;
239
+
240
+ f ( & mut that)
236
241
}
237
242
}
238
243
Original file line number Diff line number Diff line change @@ -61,4 +61,29 @@ fn with_mut_fn() {
61
61
assert_ne ! ( * bigbox, Default :: default ( ) ) ;
62
62
} )
63
63
}
64
+
65
+ // drop it, otherwise we would leak memory here
66
+ unsafe { <Box < Big > as ErasablePtr >:: unerase ( erased) } ;
67
+ }
68
+
69
+ #[ test]
70
+ fn with_mut_fn_replacethis ( ) {
71
+ let boxed: Box < Big > = Default :: default ( ) ;
72
+
73
+ let mut erased: ErasedPtr = ErasablePtr :: erase ( boxed) ;
74
+ let e1 = erased. as_ptr ( ) as usize ;
75
+ unsafe {
76
+ <Box < Big > as ErasablePtr >:: with_mut ( & mut erased, |bigbox| {
77
+ let mut newboxed: Box < Big > = Default :: default ( ) ;
78
+ newboxed. 0 [ 0 ] = 123456 ;
79
+ * bigbox = newboxed;
80
+ assert_ne ! ( * bigbox, Default :: default ( ) ) ;
81
+ } )
82
+ }
83
+
84
+ let e2 = erased. as_ptr ( ) as usize ;
85
+ assert_ne ! ( e1, e2) ;
86
+
87
+ // drop it, otherwise we would leak memory here
88
+ unsafe { <Box < Big > as ErasablePtr >:: unerase ( erased) } ;
64
89
}
You can’t perform that action at this time.
0 commit comments