11//! Helper module for some internals, most users don't need to interact with it.
22
3+ use core:: marker:: PhantomData ;
4+ use core:: ptr:: NonNull ;
35use std:: {
46 cell:: UnsafeCell ,
57 error:: Error ,
@@ -42,7 +44,7 @@ impl Error for InvalidBorrow {
4244#[ derive( Debug ) ]
4345pub struct Ref < ' a , T : ?Sized + ' a > {
4446 flag : & ' a AtomicUsize ,
45- value : & ' a T ,
47+ value : NonNull < T > ,
4648}
4749
4850impl < ' a , T : ?Sized > Ref < ' a , T > {
@@ -95,7 +97,7 @@ impl<'a, T: ?Sized> Ref<'a, T> {
9597 {
9698 let val = Ref {
9799 flag : self . flag ,
98- value : f ( self . value ) ,
100+ value : NonNull :: from ( f ( & * self ) ) ,
99101 } ;
100102
101103 std:: mem:: forget ( self ) ;
@@ -108,7 +110,8 @@ impl<'a, T: ?Sized> Deref for Ref<'a, T> {
108110 type Target = T ;
109111
110112 fn deref ( & self ) -> & T {
111- self . value
113+ // SAFETY: `Ref` holds a shared borrow of the value.
114+ unsafe { self . value . as_ref ( ) }
112115 }
113116}
114117
@@ -134,7 +137,10 @@ impl<'a, T: ?Sized> Clone for Ref<'a, T> {
134137#[ derive( Debug ) ]
135138pub struct RefMut < ' a , T : ?Sized + ' a > {
136139 flag : & ' a AtomicUsize ,
137- value : & ' a mut T ,
140+ value : NonNull < T > ,
141+ // `NonNull<T>` is covariant over `T` but we use it in the place of a mutable reference so we need to be
142+ // invariant over `T`.
143+ marker : PhantomData < & ' a mut T > ,
138144}
139145
140146impl < ' a , T : ?Sized > RefMut < ' a , T > {
@@ -182,7 +188,7 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
182188 /// let b2: RefMut<'_, u32> = RefMut::map(b1, |t| &mut t.0);
183189 /// assert_eq!(*b2, 5);
184190 /// ```
185- pub fn map < U , F > ( self , f : F ) -> RefMut < ' a , U >
191+ pub fn map < U , F > ( mut self , f : F ) -> RefMut < ' a , U >
186192 where
187193 F : FnOnce ( & mut T ) -> & mut U ,
188194 U : ?Sized ,
@@ -192,7 +198,7 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
192198 // the given `RefMut`, the lifetime we created through turning the
193199 // pointer into a ref is valid.
194200 let flag = self . flag ;
195- let value = unsafe { & mut * ( self . value as * mut _ ) } ;
201+ let value = NonNull :: from ( f ( & mut * self ) ) ;
196202
197203 // We have to forget self so that we do not run `Drop`. Further it's safe
198204 // because we are creating a new `RefMut`, with the same flag, which
@@ -201,7 +207,8 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
201207
202208 RefMut {
203209 flag,
204- value : f ( value) ,
210+ value,
211+ marker : PhantomData ,
205212 }
206213 }
207214}
@@ -210,13 +217,17 @@ impl<'a, T: ?Sized> Deref for RefMut<'a, T> {
210217 type Target = T ;
211218
212219 fn deref ( & self ) -> & T {
213- self . value
220+ // SAFETY: `RefMut` holds an exclusive borrow of the value and we have a shared borrow of
221+ // `RefMut` here.
222+ unsafe { self . value . as_ref ( ) }
214223 }
215224}
216225
217226impl < ' a , T : ?Sized > DerefMut for RefMut < ' a , T > {
218227 fn deref_mut ( & mut self ) -> & mut T {
219- self . value
228+ // SAFETY: `RefMut` holds an exclusive borrow of the value and we have an exclusive borrow
229+ // of `RefMut` here.
230+ unsafe { self . value . as_mut ( ) }
220231 }
221232}
222233
@@ -261,7 +272,7 @@ impl<T> TrustCell<T> {
261272
262273 Ref {
263274 flag : & self . flag ,
264- value : unsafe { & * self . inner . get ( ) } ,
275+ value : unsafe { NonNull :: new_unchecked ( self . inner . get ( ) ) } ,
265276 }
266277 }
267278
@@ -274,7 +285,7 @@ impl<T> TrustCell<T> {
274285
275286 Ok ( Ref {
276287 flag : & self . flag ,
277- value : unsafe { & * self . inner . get ( ) } ,
288+ value : unsafe { NonNull :: new_unchecked ( self . inner . get ( ) ) } ,
278289 } )
279290 }
280291
@@ -292,7 +303,8 @@ impl<T> TrustCell<T> {
292303
293304 RefMut {
294305 flag : & self . flag ,
295- value : unsafe { & mut * self . inner . get ( ) } ,
306+ value : unsafe { NonNull :: new_unchecked ( self . inner . get ( ) ) } ,
307+ marker : PhantomData ,
296308 }
297309 }
298310
@@ -305,7 +317,8 @@ impl<T> TrustCell<T> {
305317
306318 Ok ( RefMut {
307319 flag : & self . flag ,
308- value : unsafe { & mut * self . inner . get ( ) } ,
320+ value : unsafe { NonNull :: new_unchecked ( self . inner . get ( ) ) } ,
321+ marker : PhantomData ,
309322 } )
310323 }
311324
@@ -471,22 +484,27 @@ mod tests {
471484 assert ! ( cell. try_borrow_mut( ) . is_err( ) ) ;
472485 }
473486
487+ fn make_ref < ' a , T : ?Sized > ( flag : & ' a AtomicUsize , value : & ' a T ) -> Ref < ' a , T > {
488+ Ref {
489+ flag,
490+ value : NonNull :: from ( value) ,
491+ }
492+ }
493+
474494 #[ test]
475495 fn ref_with_non_sized ( ) {
476- let r: Ref < ' _ , [ i32 ] > = Ref {
477- flag : & AtomicUsize :: new ( 1 ) ,
478- value : & [ 2 , 3 , 4 , 5 ] [ ..] ,
479- } ;
496+ let value = & [ 2 , 3 , 4 , 5 ] [ ..] ;
497+ let flag = AtomicUsize :: new ( 1 ) ;
498+ let r: Ref < ' _ , [ i32 ] > = make_ref ( & flag, value) ;
480499
481500 assert_eq ! ( & * r, & [ 2 , 3 , 4 , 5 ] [ ..] ) ;
482501 }
483502
484503 #[ test]
485504 fn ref_with_non_sized_clone ( ) {
486- let r: Ref < ' _ , [ i32 ] > = Ref {
487- flag : & AtomicUsize :: new ( 1 ) ,
488- value : & [ 2 , 3 , 4 , 5 ] [ ..] ,
489- } ;
505+ let value = & [ 2 , 3 , 4 , 5 ] [ ..] ;
506+ let flag = AtomicUsize :: new ( 1 ) ;
507+ let r: Ref < ' _ , [ i32 ] > = make_ref ( & flag, value) ;
490508 let rr = r. clone ( ) ;
491509
492510 assert_eq ! ( & * r, & [ 2 , 3 , 4 , 5 ] [ ..] ) ;
@@ -498,30 +516,35 @@ mod tests {
498516
499517 #[ test]
500518 fn ref_with_trait_obj ( ) {
501- let ra: Ref < ' _ , dyn std:: any:: Any > = Ref {
502- flag : & AtomicUsize :: new ( 1 ) ,
503- value : & 2i32 ,
504- } ;
519+ let value = & 2i32 ;
520+ let flag = AtomicUsize :: new ( 1 ) ;
521+ let ra: Ref < ' _ , dyn std:: any:: Any > = make_ref ( & flag, value) ;
505522
506523 assert_eq ! ( ra. downcast_ref:: <i32 >( ) . unwrap( ) , & 2i32 ) ;
507524 }
508525
526+ fn make_ref_mut < ' a , T : ?Sized > ( flag : & ' a AtomicUsize , value : & ' a mut T ) -> RefMut < ' a , T > {
527+ RefMut {
528+ flag,
529+ value : NonNull :: from ( value) ,
530+ marker : PhantomData ,
531+ }
532+ }
533+
509534 #[ test]
510535 fn ref_mut_with_non_sized ( ) {
511- let mut r: RefMut < ' _ , [ i32 ] > = RefMut {
512- flag : & AtomicUsize :: new ( 1 ) ,
513- value : & mut [ 2 , 3 , 4 , 5 ] [ ..] ,
514- } ;
536+ let value: & mut [ i32 ] = & mut [ 2 , 3 , 4 , 5 ] [ ..] ;
537+ let flag = AtomicUsize :: new ( 1 ) ;
538+ let mut r: RefMut < ' _ , [ i32 ] > = make_ref_mut ( & flag, value) ;
515539
516540 assert_eq ! ( & mut * r, & mut [ 2 , 3 , 4 , 5 ] [ ..] ) ;
517541 }
518542
519543 #[ test]
520544 fn ref_mut_with_trait_obj ( ) {
521- let mut ra: RefMut < ' _ , dyn std:: any:: Any > = RefMut {
522- flag : & AtomicUsize :: new ( 1 ) ,
523- value : & mut 2i32 ,
524- } ;
545+ let value = & mut 2i32 ;
546+ let flag = AtomicUsize :: new ( 1 ) ;
547+ let mut ra: RefMut < ' _ , dyn std:: any:: Any > = make_ref_mut ( & flag, value) ;
525548
526549 assert_eq ! ( ra. downcast_mut:: <i32 >( ) . unwrap( ) , & mut 2i32 ) ;
527550 }
@@ -613,4 +636,18 @@ mod tests {
613636 drop ( r) ;
614637 assert_eq ! ( cell. flag. load( Ordering :: SeqCst ) , 0 ) ;
615638 }
639+
640+ // Test intended to allow Miri to catch bugs like this scenario:
641+ // https://github.com/rust-lang/rust/issues/63787
642+ #[ test]
643+ fn drop_and_borrow_in_fn_call ( ) {
644+ fn drop_and_borrow ( cell : & TrustCell < u8 > , borrow : Ref < ' _ , u8 > ) {
645+ drop ( borrow) ;
646+ * cell. borrow_mut ( ) = 7u8 ;
647+ }
648+
649+ let a = TrustCell :: new ( 4u8 ) ;
650+ let borrow = a. borrow ( ) ;
651+ drop_and_borrow ( & a, borrow) ;
652+ }
616653}
0 commit comments