@@ -239,7 +239,7 @@ use core::fmt;
239239use core:: hash:: { Hash , Hasher } ;
240240use core:: intrinsics:: abort;
241241use core:: marker:: { self , Unpin , Unsize , PhantomData } ;
242- use core:: mem:: { self , align_of_val, forget, size_of_val} ;
242+ use core:: mem:: { self , align_of , align_of_val, forget, size_of_val} ;
243243use core:: ops:: { Deref , Receiver , CoerceUnsized , DispatchFromDyn } ;
244244use core:: pin:: Pin ;
245245use core:: ptr:: { self , NonNull } ;
@@ -416,11 +416,7 @@ impl<T: ?Sized> Rc<T> {
416416 /// ```
417417 #[ stable( feature = "rc_raw" , since = "1.17.0" ) ]
418418 pub unsafe fn from_raw ( ptr : * const T ) -> Self {
419- // Align the unsized value to the end of the RcBox.
420- // Because it is ?Sized, it will always be the last field in memory.
421- let align = align_of_val ( & * ptr) ;
422- let layout = Layout :: new :: < RcBox < ( ) > > ( ) ;
423- let offset = ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize ;
419+ let offset = data_offset ( ptr) ;
424420
425421 // Reverse the offset to find the original RcBox.
426422 let fake_ptr = ptr as * mut RcBox < T > ;
@@ -1262,6 +1258,143 @@ impl<T> Weak<T> {
12621258 ptr : NonNull :: new ( usize:: MAX as * mut RcBox < T > ) . expect ( "MAX is not 0" ) ,
12631259 }
12641260 }
1261+
1262+ /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
1263+ ///
1264+ /// It is up to the caller to ensure that the object is still alive when accessing it through
1265+ /// the pointer.
1266+ ///
1267+ /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
1268+ ///
1269+ /// # Examples
1270+ ///
1271+ /// ```
1272+ /// #![feature(weak_into_raw)]
1273+ ///
1274+ /// use std::rc::{Rc, Weak};
1275+ /// use std::ptr;
1276+ ///
1277+ /// let strong = Rc::new(42);
1278+ /// let weak = Rc::downgrade(&strong);
1279+ /// // Both point to the same object
1280+ /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
1281+ /// // The strong here keeps it alive, so we can still access the object.
1282+ /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1283+ ///
1284+ /// drop(strong);
1285+ /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
1286+ /// // undefined behaviour.
1287+ /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1288+ /// ```
1289+ ///
1290+ /// [`null`]: ../../std/ptr/fn.null.html
1291+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1292+ pub fn as_raw ( this : & Self ) -> * const T {
1293+ match this. inner ( ) {
1294+ None => ptr:: null ( ) ,
1295+ Some ( inner) => {
1296+ let offset = data_offset_sized :: < T > ( ) ;
1297+ let ptr = inner as * const RcBox < T > ;
1298+ // Note: while the pointer we create may already point to dropped value, the
1299+ // allocation still lives (it must hold the weak point as long as we are alive).
1300+ // Therefore, the offset is OK to do, it won't get out of the allocation.
1301+ let ptr = unsafe { ( ptr as * const u8 ) . offset ( offset) } ;
1302+ ptr as * const T
1303+ }
1304+ }
1305+ }
1306+
1307+ /// Consumes the `Weak<T>` and turns it into a raw pointer.
1308+ ///
1309+ /// This converts the weak pointer into a raw pointer, preserving the original weak count. It
1310+ /// can be turned back into the `Weak<T>` with [`from_raw`].
1311+ ///
1312+ /// The same restrictions of accessing the target of the pointer as with
1313+ /// [`as_raw`] apply.
1314+ ///
1315+ /// # Examples
1316+ ///
1317+ /// ```
1318+ /// #![feature(weak_into_raw)]
1319+ ///
1320+ /// use std::rc::{Rc, Weak};
1321+ ///
1322+ /// let strong = Rc::new(42);
1323+ /// let weak = Rc::downgrade(&strong);
1324+ /// let raw = Weak::into_raw(weak);
1325+ ///
1326+ /// assert_eq!(1, Rc::weak_count(&strong));
1327+ /// assert_eq!(42, unsafe { *raw });
1328+ ///
1329+ /// drop(unsafe { Weak::from_raw(raw) });
1330+ /// assert_eq!(0, Rc::weak_count(&strong));
1331+ /// ```
1332+ ///
1333+ /// [`from_raw`]: struct.Weak.html#method.from_raw
1334+ /// [`as_raw`]: struct.Weak.html#method.as_raw
1335+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1336+ pub fn into_raw ( this : Self ) -> * const T {
1337+ let result = Self :: as_raw ( & this) ;
1338+ mem:: forget ( this) ;
1339+ result
1340+ }
1341+
1342+ /// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>`.
1343+ ///
1344+ /// This can be used to safely get a strong reference (by calling [`upgrade`]
1345+ /// later) or to deallocate the weak count by dropping the `Weak<T>`.
1346+ ///
1347+ /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
1348+ /// returned.
1349+ ///
1350+ /// # Safety
1351+ ///
1352+ /// The pointer must represent one valid weak count. In other words, it must point to `T` which
1353+ /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
1354+ /// 0. It is allowed for the strong count to be 0.
1355+ ///
1356+ /// # Examples
1357+ ///
1358+ /// ```
1359+ /// #![feature(weak_into_raw)]
1360+ ///
1361+ /// use std::rc::{Rc, Weak};
1362+ ///
1363+ /// let strong = Rc::new(42);
1364+ ///
1365+ /// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
1366+ /// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
1367+ ///
1368+ /// assert_eq!(2, Rc::weak_count(&strong));
1369+ ///
1370+ /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
1371+ /// assert_eq!(1, Rc::weak_count(&strong));
1372+ ///
1373+ /// drop(strong);
1374+ ///
1375+ /// // Decrement the last weak count.
1376+ /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
1377+ /// ```
1378+ ///
1379+ /// [`null`]: ../../std/ptr/fn.null.html
1380+ /// [`into_raw`]: struct.Weak.html#method.into_raw
1381+ /// [`upgrade`]: struct.Weak.html#method.upgrade
1382+ /// [`Rc`]: struct.Rc.html
1383+ /// [`Weak`]: struct.Weak.html
1384+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1385+ pub unsafe fn from_raw ( ptr : * const T ) -> Self {
1386+ if ptr. is_null ( ) {
1387+ Self :: new ( )
1388+ } else {
1389+ // See Rc::from_raw for details
1390+ let offset = data_offset ( ptr) ;
1391+ let fake_ptr = ptr as * mut RcBox < T > ;
1392+ let ptr = set_data_ptr ( fake_ptr, ( ptr as * mut u8 ) . offset ( -offset) ) ;
1393+ Weak {
1394+ ptr : NonNull :: new ( ptr) . expect ( "Invalid pointer passed to from_raw" ) ,
1395+ }
1396+ }
1397+ }
12651398}
12661399
12671400pub ( crate ) fn is_dangling < T : ?Sized > ( ptr : NonNull < T > ) -> bool {
@@ -2007,3 +2140,20 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
20072140
20082141#[ stable( feature = "pin" , since = "1.33.0" ) ]
20092142impl < T : ?Sized > Unpin for Rc < T > { }
2143+
2144+ unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2145+ // Align the unsized value to the end of the RcBox.
2146+ // Because it is ?Sized, it will always be the last field in memory.
2147+ let align = align_of_val ( & * ptr) ;
2148+ let layout = Layout :: new :: < RcBox < ( ) > > ( ) ;
2149+ ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2150+ }
2151+
2152+ /// Computes the offset of the data field within ArcInner.
2153+ ///
2154+ /// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2155+ fn data_offset_sized < T > ( ) -> isize {
2156+ let align = align_of :: < T > ( ) ;
2157+ let layout = Layout :: new :: < RcBox < ( ) > > ( ) ;
2158+ ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2159+ }
0 commit comments