@@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
1616use core:: intrinsics:: abort;
1717use core:: iter;
1818use core:: marker:: { PhantomData , Unpin , Unsize } ;
19- use core:: mem:: { self , align_of , align_of_val, size_of_val} ;
19+ use core:: mem:: { self , align_of_val, size_of_val} ;
2020use core:: ops:: { CoerceUnsized , Deref , DispatchFromDyn , Receiver } ;
2121use core:: pin:: Pin ;
2222use core:: ptr:: { self , NonNull } ;
@@ -267,6 +267,7 @@ pub struct Weak<T: ?Sized> {
267267 // `Weak::new` sets this to `usize::MAX` so that it doesn’t need
268268 // to allocate space on the heap. That's not a value a real pointer
269269 // will ever have because RcBox has alignment at least 2.
270+ // This is only possible when `T: Sized`; unsized `T` never dangle.
270271 ptr : NonNull < ArcInner < T > > ,
271272}
272273
@@ -590,17 +591,11 @@ impl<T: ?Sized> Arc<T> {
590591 #[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
591592 pub fn as_ptr ( this : & Self ) -> * const T {
592593 let ptr: * mut ArcInner < T > = NonNull :: as_ptr ( this. ptr ) ;
593- let fake_ptr = ptr as * mut T ;
594594
595- // SAFETY: This cannot go through Deref::deref.
596- // Instead, we manually offset the pointer rather than manifesting a reference.
597- // This is so that the returned pointer retains the same provenance as our pointer.
598- // This is required so that e.g. `get_mut` can write through the pointer
599- // after the Arc is recovered through `from_raw`.
600- unsafe {
601- let offset = data_offset ( & ( * ptr) . data ) ;
602- set_data_ptr ( fake_ptr, ( ptr as * mut u8 ) . offset ( offset) )
603- }
595+ // SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because
596+ // this is required to retain raw/mut provenance such that e.g. `get_mut` can
597+ // write through the pointer after the Rc is recovered through `from_raw`.
598+ unsafe { & raw const ( * ptr) . data }
604599 }
605600
606601 /// Constructs an `Arc<T>` from a raw pointer.
@@ -1476,9 +1471,18 @@ impl<T> Weak<T> {
14761471 /// [`null`]: ../../std/ptr/fn.null.html
14771472 #[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
14781473 pub fn as_ptr ( & self ) -> * const T {
1479- let offset = data_offset_sized :: < T > ( ) ;
1480- let ptr = self . ptr . cast :: < u8 > ( ) . as_ptr ( ) . wrapping_offset ( offset) ;
1481- ptr as * const T
1474+ let ptr: * mut ArcInner < T > = NonNull :: as_ptr ( self . ptr ) ;
1475+
1476+ // SAFETY: we must offset the pointer manually, and said pointer may be
1477+ // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1478+ // because we know that a pointer to unsized T was derived from a real
1479+ // unsized T, as dangling weaks are only created for sized T. wrapping_offset
1480+ // is used so that we can use the same code path for the non-dangling
1481+ // unsized case and the potentially dangling sized case.
1482+ unsafe {
1483+ let offset = data_offset ( ptr as * mut T ) ;
1484+ set_data_ptr ( ptr as * mut T , ( ptr as * mut u8 ) . wrapping_offset ( offset) )
1485+ }
14821486 }
14831487
14841488 /// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -2270,7 +2274,16 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
22702274#[ stable( feature = "pin" , since = "1.33.0" ) ]
22712275impl < T : ?Sized > Unpin for Arc < T > { }
22722276
2273- /// Computes the offset of the data field within `ArcInner`.
2277+ /// Get the offset within an `ArcInner` for
2278+ /// a payload of type described by a pointer.
2279+ ///
2280+ /// # Safety
2281+ ///
2282+ /// This has the same safety requirements as `align_of_val_raw`. In effect:
2283+ ///
2284+ /// - This function is safe for any argument if `T` is sized, and
2285+ /// - if `T` is unsized, the pointer must have appropriate pointer metadata
2286+ /// aquired from the real instance that you are getting this offset for.
22742287unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
22752288 // Align the unsized value to the end of the `ArcInner`.
22762289 // Because it is `?Sized`, it will always be the last field in memory.
@@ -2279,13 +2292,6 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
22792292 unsafe { data_offset_align ( align_of_val ( & * ptr) ) }
22802293}
22812294
2282- /// Computes the offset of the data field within `ArcInner`.
2283- ///
2284- /// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2285- fn data_offset_sized < T > ( ) -> isize {
2286- data_offset_align ( align_of :: < T > ( ) )
2287- }
2288-
22892295#[ inline]
22902296fn data_offset_align ( align : usize ) -> isize {
22912297 let layout = Layout :: new :: < ArcInner < ( ) > > ( ) ;
0 commit comments