diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a96be57143d38..b7f1edd332d80 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1780,11 +1780,11 @@ impl Weak { let ptr: *mut RcBox = NonNull::as_ptr(self.ptr); // SAFETY: we must offset the pointer manually, and said pointer may be - // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call, - // because we know that a pointer to unsized T was derived from a real - // unsized T, as dangling weaks are only created for sized T. wrapping_offset - // is used so that we can use the same code path for the non-dangling - // unsized case and the potentially dangling sized case. + // a dangling weak (usize::MAX). data_offset is safe to call, because we know + // that a pointer to unsized T was acquired by unsize coercion from an Rc/Weak + // of sized T. (Weak::new can only construct dangling pointers for sized T). + // wrapping_offset is used so that we can use the same code path for the + // dangling and non-dangling cases. unsafe { let offset = data_offset(ptr as *mut T); set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset)) @@ -1874,7 +1874,7 @@ impl Weak { let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcBox. - // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized). + // SAFETY: we use wrapping_offset here because the pointer may be dangling. let ptr = unsafe { set_data_ptr(ptr as *mut RcBox, (ptr as *mut u8).wrapping_offset(-offset)) }; @@ -2208,13 +2208,11 @@ impl Unpin for Rc {} /// This has the same safety requirements as `align_of_val_raw`. In effect: /// /// - This function is safe for any argument if `T` is sized, and -/// - if `T` is unsized, the pointer must have appropriate pointer metadata -/// acquired from the real instance that you are getting this offset for. +/// - if `T` is unsized, the pointer must have been acquired from an unsize +/// coercion (but may be invalid, such as from Weak::new). unsafe fn data_offset(ptr: *const T) -> isize { // Align the unsized value to the end of the `RcBox`. - // Because it is ?Sized, it will always be the last field in memory. - // Note: This is a detail of the current implementation of the compiler, - // and is not a guaranteed language detail. Do not rely on it outside of std. + // As RcBox is #[repr(C)], it will always be the last field in memory. unsafe { data_offset_align(align_of_val_raw(ptr)) } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9d478a302e96c..0f9d1e6678979 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -273,7 +273,6 @@ pub struct Weak { // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer // will ever have because RcBox has alignment at least 2. - // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, } @@ -1566,11 +1565,11 @@ impl Weak { let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); // SAFETY: we must offset the pointer manually, and said pointer may be - // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call, - // because we know that a pointer to unsized T was derived from a real - // unsized T, as dangling weaks are only created for sized T. wrapping_offset - // is used so that we can use the same code path for the non-dangling - // unsized case and the potentially dangling sized case. + // a dangling weak (usize::MAX). data_offset is safe to call, because we know + // that a pointer to unsized T was acquired by unsize coercion from an Rc/Weak + // of sized T. (Weak::new can only construct dangling pointers for sized T). + // wrapping_offset is used so that we can use the same code path for the + // dangling and non-dangling cases. unsafe { let offset = data_offset(ptr as *mut T); set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset)) @@ -1628,6 +1627,7 @@ impl Weak { /// takes ownership of one weak reference currently represented as a raw pointer (the weak /// count is not modified by this operation) and therefore it must be paired with a previous /// call to [`into_raw`]. + /// /// # Examples /// /// ``` @@ -1660,7 +1660,7 @@ impl Weak { let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original ArcInner. - // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized) + // SAFETY: we use wrapping_offset here because the pointer may be dangling. let ptr = unsafe { set_data_ptr(ptr as *mut ArcInner, (ptr as *mut u8).wrapping_offset(-offset)) };