@@ -1862,7 +1862,7 @@ struct WeakInner<'a> {
18621862 strong : & ' a Cell < usize > ,
18631863}
18641864
1865- impl < T > Weak < T > {
1865+ impl < T : ? Sized > Weak < T > {
18661866 /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
18671867 ///
18681868 /// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1892,15 +1892,17 @@ impl<T> Weak<T> {
18921892 pub fn as_ptr ( & self ) -> * const T {
18931893 let ptr: * mut RcBox < T > = NonNull :: as_ptr ( self . ptr ) ;
18941894
1895- // SAFETY: we must offset the pointer manually, and said pointer may be
1896- // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1897- // because we know that a pointer to unsized T was derived from a real
1898- // unsized T, as dangling weaks are only created for sized T. wrapping_offset
1899- // is used so that we can use the same code path for the non-dangling
1900- // unsized case and the potentially dangling sized case.
1901- unsafe {
1902- let offset = data_offset ( ptr as * mut T ) ;
1903- set_data_ptr ( ptr as * mut T , ( ptr as * mut u8 ) . wrapping_offset ( offset) )
1895+ if is_dangling ( self . ptr ) {
1896+ // If the pointer is dangling, we return a null pointer as the dangling sentinel.
1897+ // We can't return the usize::MAX sentinel, as that could valid if T is ZST.
1898+ // SAFETY: we have to return a known sentinel here that cannot be produced for
1899+ // a valid pointer, so that `from_raw` can reverse this transformation.
1900+ ( ptr as * mut T ) . set_ptr_value ( ptr:: null_mut ( ) )
1901+ } else {
1902+ // SAFETY: If the pointer is not dangling, it describes to a valid allocation.
1903+ // The payload may be dropped at this point, and we have to maintain provenance,
1904+ // so use raw pointer manipulation.
1905+ unsafe { & raw mut ( * ptr) . value }
19041906 }
19051907 }
19061908
@@ -1982,22 +1984,25 @@ impl<T> Weak<T> {
19821984 /// [`new`]: Weak::new
19831985 #[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
19841986 pub unsafe fn from_raw ( ptr : * const T ) -> Self {
1985- // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
19861987 // See Weak::as_ptr for context on how the input pointer is derived.
1987- let offset = unsafe { data_offset ( ptr) } ;
19881988
1989- // Reverse the offset to find the original RcBox.
1990- // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
1991- let ptr = unsafe {
1992- set_data_ptr ( ptr as * mut RcBox < T > , ( ptr as * mut u8 ) . wrapping_offset ( -offset) )
1989+ let ptr = if ptr. is_null ( ) {
1990+ // If we get a null pointer, this is a dangling weak.
1991+ // SAFETY: this is the same sentinel as used in Weak::new and is_dangling
1992+ ( ptr as * mut RcBox < T > ) . set_ptr_value ( usize:: MAX as * mut _ )
1993+ } else {
1994+ // Otherwise, this describes a real allocation.
1995+ // SAFETY: data_offset is safe to call, as ptr describes a real allocation.
1996+ let offset = unsafe { data_offset ( ptr) } ;
1997+ // Thus, we reverse the offset to get the whole RcBox.
1998+ // SAFETY: the pointer originated from a Weak, so this offset is safe.
1999+ unsafe { ( ptr as * mut RcBox < T > ) . set_ptr_value ( ( ptr as * mut u8 ) . offset ( -offset) ) }
19932000 } ;
19942001
19952002 // SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
19962003 Weak { ptr : unsafe { NonNull :: new_unchecked ( ptr) } }
19972004 }
1998- }
19992005
2000- impl < T : ?Sized > Weak < T > {
20012006 /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
20022007 /// dropping of the inner value if successful.
20032008 ///
0 commit comments