@@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
16
16
use core:: intrinsics:: abort;
17
17
use core:: iter;
18
18
use 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} ;
20
20
use core:: ops:: { CoerceUnsized , Deref , DispatchFromDyn , Receiver } ;
21
21
use core:: pin:: Pin ;
22
22
use core:: ptr:: { self , NonNull } ;
@@ -267,6 +267,7 @@ pub struct Weak<T: ?Sized> {
267
267
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
268
268
// to allocate space on the heap. That's not a value a real pointer
269
269
// will ever have because RcBox has alignment at least 2.
270
+ // This is only possible when `T: Sized`; unsized `T` never dangle.
270
271
ptr : NonNull < ArcInner < T > > ,
271
272
}
272
273
@@ -590,17 +591,11 @@ impl<T: ?Sized> Arc<T> {
590
591
#[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
591
592
pub fn as_ptr ( this : & Self ) -> * const T {
592
593
let ptr: * mut ArcInner < T > = NonNull :: as_ptr ( this. ptr ) ;
593
- let fake_ptr = ptr as * mut T ;
594
594
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 }
604
599
}
605
600
606
601
/// Constructs an `Arc<T>` from a raw pointer.
@@ -1476,9 +1471,18 @@ impl<T> Weak<T> {
1476
1471
/// [`null`]: ../../std/ptr/fn.null.html
1477
1472
#[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
1478
1473
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
+ }
1482
1486
}
1483
1487
1484
1488
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -2270,7 +2274,16 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
2270
2274
#[ stable( feature = "pin" , since = "1.33.0" ) ]
2271
2275
impl < T : ?Sized > Unpin for Arc < T > { }
2272
2276
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.
2274
2287
unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2275
2288
// Align the unsized value to the end of the `ArcInner`.
2276
2289
// 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 {
2279
2292
unsafe { data_offset_align ( align_of_val ( & * ptr) ) }
2280
2293
}
2281
2294
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
-
2289
2295
#[ inline]
2290
2296
fn data_offset_align ( align : usize ) -> isize {
2291
2297
let layout = Layout :: new :: < ArcInner < ( ) > > ( ) ;
0 commit comments