@@ -353,6 +353,26 @@ impl<T> Rc<T> {
353
353
/// to upgrade the weak reference before this function returns will result
354
354
/// in a `None` value. However, the weak reference may be cloned freely and
355
355
/// stored for use at a later time.
356
+ ///
357
+ /// # Examples
358
+ ///
359
+ /// ```
360
+ /// #![feature(arc_new_cyclic)]
361
+ /// #![allow(dead_code)]
362
+ /// use std::rc::{Rc, Weak};
363
+ ///
364
+ /// struct Gadget {
365
+ /// self_weak: Weak<Self>,
366
+ /// // ... more fields
367
+ /// }
368
+ /// impl Gadget {
369
+ /// pub fn new() -> Rc<Self> {
370
+ /// Rc::new_cyclic(|self_weak| {
371
+ /// Gadget { self_weak: self_weak.clone(), /* ... */ }
372
+ /// })
373
+ /// }
374
+ /// }
375
+ /// ```
356
376
#[ unstable( feature = "arc_new_cyclic" , issue = "75861" ) ]
357
377
pub fn new_cyclic ( data_fn : impl FnOnce ( & Weak < T > ) -> T ) -> Rc < T > {
358
378
// Construct the inner in the "uninitialized" state with a single
@@ -829,8 +849,8 @@ impl<T: ?Sized> Rc<T> {
829
849
let offset = unsafe { data_offset ( ptr) } ;
830
850
831
851
// Reverse the offset to find the original RcBox.
832
- let fake_ptr = ptr as * mut RcBox < T > ;
833
- let rc_ptr = unsafe { set_data_ptr ( fake_ptr , ( ptr as * mut u8 ) . offset ( -offset) ) } ;
852
+ let rc_ptr =
853
+ unsafe { ( ptr as * mut RcBox < T > ) . set_ptr_value ( ( ptr as * mut u8 ) . offset ( -offset) ) } ;
834
854
835
855
unsafe { Self :: from_ptr ( rc_ptr) }
836
856
}
@@ -850,7 +870,7 @@ impl<T: ?Sized> Rc<T> {
850
870
pub fn downgrade ( this : & Self ) -> Weak < T > {
851
871
this. inner ( ) . inc_weak ( ) ;
852
872
// Make sure we do not create a dangling Weak
853
- debug_assert ! ( !is_dangling( this. ptr) ) ;
873
+ debug_assert ! ( !is_dangling( this. ptr. as_ptr ( ) ) ) ;
854
874
Weak { ptr : this. ptr }
855
875
}
856
876
@@ -1164,7 +1184,7 @@ impl<T: ?Sized> Rc<T> {
1164
1184
Self :: allocate_for_layout (
1165
1185
Layout :: for_value ( & * ptr) ,
1166
1186
|layout| Global . allocate ( layout) ,
1167
- |mem| set_data_ptr ( ptr as * mut T , mem ) as * mut RcBox < T > ,
1187
+ |mem| ( ptr as * mut RcBox < T > ) . set_ptr_value ( mem ) ,
1168
1188
)
1169
1189
}
1170
1190
}
@@ -1203,20 +1223,7 @@ impl<T> Rc<[T]> {
1203
1223
)
1204
1224
}
1205
1225
}
1206
- }
1207
-
1208
- /// Sets the data pointer of a `?Sized` raw pointer.
1209
- ///
1210
- /// For a slice/trait object, this sets the `data` field and leaves the rest
1211
- /// unchanged. For a sized raw pointer, this simply sets the pointer.
1212
- unsafe fn set_data_ptr < T : ?Sized , U > ( mut ptr : * mut T , data : * mut U ) -> * mut T {
1213
- unsafe {
1214
- ptr:: write ( & mut ptr as * mut _ as * mut * mut u8 , data as * mut u8 ) ;
1215
- }
1216
- ptr
1217
- }
1218
1226
1219
- impl < T > Rc < [ T ] > {
1220
1227
/// Copy elements from slice into newly allocated Rc<\[T\]>
1221
1228
///
1222
1229
/// Unsafe because the caller must either take ownership or bind `T: Copy`
@@ -1860,8 +1867,8 @@ impl<T> Weak<T> {
1860
1867
}
1861
1868
}
1862
1869
1863
- pub ( crate ) fn is_dangling < T : ?Sized > ( ptr : NonNull < T > ) -> bool {
1864
- let address = ptr. as_ptr ( ) as * mut ( ) as usize ;
1870
+ pub ( crate ) fn is_dangling < T : ?Sized > ( ptr : * mut T ) -> bool {
1871
+ let address = ptr as * mut ( ) as usize ;
1865
1872
address == usize:: MAX
1866
1873
}
1867
1874
@@ -1872,7 +1879,7 @@ struct WeakInner<'a> {
1872
1879
strong : & ' a Cell < usize > ,
1873
1880
}
1874
1881
1875
- impl < T > Weak < T > {
1882
+ impl < T : ? Sized > Weak < T > {
1876
1883
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
1877
1884
///
1878
1885
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1902,15 +1909,15 @@ impl<T> Weak<T> {
1902
1909
pub fn as_ptr ( & self ) -> * const T {
1903
1910
let ptr: * mut RcBox < T > = NonNull :: as_ptr ( self . ptr ) ;
1904
1911
1905
- // SAFETY: we must offset the pointer manually, and said pointer may be
1906
- // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1907
- // because we know that a pointer to unsized T was derived from a real
1908
- // unsized T, as dangling weaks are only created for sized T. wrapping_offset
1909
- // is used so that we can use the same code path for the non-dangling
1910
- // unsized case and the potentially dangling sized case .
1911
- unsafe {
1912
- let offset = data_offset ( ptr as * mut T ) ;
1913
- set_data_ptr ( ptr as * mut T , ( ptr as * mut u8 ) . wrapping_offset ( offset ) )
1912
+ if is_dangling ( ptr ) {
1913
+ // If the pointer is dangling, we return the sentinel directly. This cannot be
1914
+ // a valid payload address, as the payload is at least as aligned as RcBox (usize).
1915
+ ptr as * const T
1916
+ } else {
1917
+ // SAFETY: if is_dangling returns false, then the pointer is dereferencable .
1918
+ // The payload may be dropped at this point, and we have to maintain provenance,
1919
+ // so use raw pointer manipulation.
1920
+ unsafe { & raw const ( * ptr ) . value }
1914
1921
}
1915
1922
}
1916
1923
@@ -1992,22 +1999,24 @@ impl<T> Weak<T> {
1992
1999
/// [`new`]: Weak::new
1993
2000
#[ stable( feature = "weak_into_raw" , since = "1.45.0" ) ]
1994
2001
pub unsafe fn from_raw ( ptr : * const T ) -> Self {
1995
- // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
1996
2002
// See Weak::as_ptr for context on how the input pointer is derived.
1997
- let offset = unsafe { data_offset ( ptr) } ;
1998
2003
1999
- // Reverse the offset to find the original RcBox.
2000
- // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
2001
- let ptr = unsafe {
2002
- set_data_ptr ( ptr as * mut RcBox < T > , ( ptr as * mut u8 ) . wrapping_offset ( -offset) )
2004
+ let ptr = if is_dangling ( ptr as * mut T ) {
2005
+ // This is a dangling Weak.
2006
+ ptr as * mut RcBox < T >
2007
+ } else {
2008
+ // Otherwise, we're guaranteed the pointer came from a nondangling Weak.
2009
+ // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
2010
+ let offset = unsafe { data_offset ( ptr) } ;
2011
+ // Thus, we reverse the offset to get the whole RcBox.
2012
+ // SAFETY: the pointer originated from a Weak, so this offset is safe.
2013
+ unsafe { ( ptr as * mut RcBox < T > ) . set_ptr_value ( ( ptr as * mut u8 ) . offset ( -offset) ) }
2003
2014
} ;
2004
2015
2005
2016
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
2006
2017
Weak { ptr : unsafe { NonNull :: new_unchecked ( ptr) } }
2007
2018
}
2008
- }
2009
2019
2010
- impl < T : ?Sized > Weak < T > {
2011
2020
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
2012
2021
/// dropping of the inner value if successful.
2013
2022
///
@@ -2070,7 +2079,7 @@ impl<T: ?Sized> Weak<T> {
2070
2079
/// (i.e., when this `Weak` was created by `Weak::new`).
2071
2080
#[ inline]
2072
2081
fn inner ( & self ) -> Option < WeakInner < ' _ > > {
2073
- if is_dangling ( self . ptr ) {
2082
+ if is_dangling ( self . ptr . as_ptr ( ) ) {
2074
2083
None
2075
2084
} else {
2076
2085
// We are careful to *not* create a reference covering the "data" field, as
@@ -2325,21 +2334,19 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
2325
2334
#[ stable( feature = "pin" , since = "1.33.0" ) ]
2326
2335
impl < T : ?Sized > Unpin for Rc < T > { }
2327
2336
2328
- /// Get the offset within an `RcBox` for
2329
- /// a payload of type described by a pointer.
2337
+ /// Get the offset within an `RcBox` for the payload behind a pointer.
2330
2338
///
2331
2339
/// # Safety
2332
2340
///
2333
- /// This has the same safety requirements as `align_of_val_raw`. In effect:
2334
- ///
2335
- /// - This function is safe for any argument if `T` is sized, and
2336
- /// - if `T` is unsized, the pointer must have appropriate pointer metadata
2337
- /// acquired from the real instance that you are getting this offset for.
2341
+ /// The pointer must point to (and have valid metadata for) a previously
2342
+ /// valid instance of T, but the T is allowed to be dropped.
2338
2343
unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2339
- // Align the unsized value to the end of the `RcBox`.
2340
- // Because it is ?Sized, it will always be the last field in memory.
2341
- // Note: This is a detail of the current implementation of the compiler,
2342
- // and is not a guaranteed language detail. Do not rely on it outside of std.
2344
+ // Align the unsized value to the end of the RcBox.
2345
+ // Because RcBox is repr(C), it will always be the last field in memory.
2346
+ // SAFETY: since the only unsized types possible are slices, trait objects,
2347
+ // and extern types, the input safety requirement is currently enough to
2348
+ // satisfy the requirements of align_of_val_raw; this is an implementation
2349
+ // detail of the language that may not be relied upon outside of std.
2343
2350
unsafe { data_offset_align ( align_of_val_raw ( ptr) ) }
2344
2351
}
2345
2352
0 commit comments