@@ -239,7 +239,7 @@ use core::fmt;
239
239
use core:: hash:: { Hash , Hasher } ;
240
240
use core:: intrinsics:: abort;
241
241
use 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} ;
243
243
use core:: ops:: { Deref , Receiver , CoerceUnsized , DispatchFromDyn } ;
244
244
use core:: pin:: Pin ;
245
245
use core:: ptr:: { self , NonNull } ;
@@ -416,11 +416,7 @@ impl<T: ?Sized> Rc<T> {
416
416
/// ```
417
417
#[ stable( feature = "rc_raw" , since = "1.17.0" ) ]
418
418
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) ;
424
420
425
421
// Reverse the offset to find the original RcBox.
426
422
let fake_ptr = ptr as * mut RcBox < T > ;
@@ -1262,6 +1258,143 @@ impl<T> Weak<T> {
1262
1258
ptr : NonNull :: new ( usize:: MAX as * mut RcBox < T > ) . expect ( "MAX is not 0" ) ,
1263
1259
}
1264
1260
}
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
+ }
1265
1398
}
1266
1399
1267
1400
pub ( crate ) fn is_dangling < T : ?Sized > ( ptr : NonNull < T > ) -> bool {
@@ -2007,3 +2140,20 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
2007
2140
2008
2141
#[ stable( feature = "pin" , since = "1.33.0" ) ]
2009
2142
impl < 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