@@ -253,14 +253,15 @@ use core::hash::{Hash, Hasher};
253
253
use core:: intrinsics:: abort;
254
254
use core:: marker;
255
255
use core:: marker:: { Unsize , PhantomData } ;
256
- use core:: mem:: { self , align_of_val, forget, size_of_val, uninitialized } ;
256
+ use core:: mem:: { self , align_of_val, forget, size_of_val} ;
257
257
use core:: ops:: Deref ;
258
258
use core:: ops:: CoerceUnsized ;
259
259
use core:: ptr:: { self , NonNull } ;
260
260
use core:: convert:: From ;
261
261
262
262
use alloc:: { Global , Alloc , Layout , box_free, handle_alloc_error} ;
263
263
use string:: String ;
264
+ use sync:: is_dangling;
264
265
use vec:: Vec ;
265
266
266
267
struct RcBox < T : ?Sized > {
@@ -1153,6 +1154,10 @@ impl<T> From<Vec<T>> for Rc<[T]> {
1153
1154
/// [`None`]: ../../std/option/enum.Option.html#variant.None
1154
1155
#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
1155
1156
pub struct Weak < T : ?Sized > {
1157
+ // This is a `NonNull` to allow optimizing the size of this type in enums,
1158
+ // but it is not necessarily a valid pointer.
1159
+ // `Weak::new` sets this to a dangling pointer so that it doesn’t need
1160
+ // to allocate space on the heap.
1156
1161
ptr : NonNull < RcBox < T > > ,
1157
1162
}
1158
1163
@@ -1165,8 +1170,8 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
1165
1170
impl < T : ?Sized + Unsize < U > , U : ?Sized > CoerceUnsized < Weak < U > > for Weak < T > { }
1166
1171
1167
1172
impl < T > Weak < T > {
1168
- /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
1169
- /// it. Calling [`upgrade`] on the return value always gives [`None`].
1173
+ /// Constructs a new `Weak<T>`, without allocating any memory.
1174
+ /// Calling [`upgrade`] on the return value always gives [`None`].
1170
1175
///
1171
1176
/// [`upgrade`]: struct.Weak.html#method.upgrade
1172
1177
/// [`None`]: ../../std/option/enum.Option.html
@@ -1181,14 +1186,8 @@ impl<T> Weak<T> {
1181
1186
/// ```
1182
1187
#[ stable( feature = "downgraded_weak" , since = "1.10.0" ) ]
1183
1188
pub fn new ( ) -> Weak < T > {
1184
- unsafe {
1185
- Weak {
1186
- ptr : Box :: into_raw_non_null ( box RcBox {
1187
- strong : Cell :: new ( 0 ) ,
1188
- weak : Cell :: new ( 1 ) ,
1189
- value : uninitialized ( ) ,
1190
- } ) ,
1191
- }
1189
+ Weak {
1190
+ ptr : NonNull :: dangling ( ) ,
1192
1191
}
1193
1192
}
1194
1193
}
@@ -1222,13 +1221,25 @@ impl<T: ?Sized> Weak<T> {
1222
1221
/// ```
1223
1222
#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
1224
1223
pub fn upgrade ( & self ) -> Option < Rc < T > > {
1225
- if self . strong ( ) == 0 {
1224
+ let inner = self . inner ( ) ?;
1225
+ if inner. strong ( ) == 0 {
1226
1226
None
1227
1227
} else {
1228
- self . inc_strong ( ) ;
1228
+ inner . inc_strong ( ) ;
1229
1229
Some ( Rc { ptr : self . ptr , phantom : PhantomData } )
1230
1230
}
1231
1231
}
1232
+
1233
+ /// Return `None` when the pointer is dangling and there is no allocated `RcBox`,
1234
+ /// i.e. this `Weak` was created by `Weak::new`
1235
+ #[ inline]
1236
+ fn inner ( & self ) -> Option < & RcBox < T > > {
1237
+ if is_dangling ( self . ptr ) {
1238
+ None
1239
+ } else {
1240
+ Some ( unsafe { self . ptr . as_ref ( ) } )
1241
+ }
1242
+ }
1232
1243
}
1233
1244
1234
1245
#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
@@ -1258,12 +1269,14 @@ impl<T: ?Sized> Drop for Weak<T> {
1258
1269
/// assert!(other_weak_foo.upgrade().is_none());
1259
1270
/// ```
1260
1271
fn drop ( & mut self ) {
1261
- unsafe {
1262
- self . dec_weak ( ) ;
1272
+ if let Some ( inner ) = self . inner ( ) {
1273
+ inner . dec_weak ( ) ;
1263
1274
// the weak count starts at 1, and will only go to zero if all
1264
1275
// the strong pointers have disappeared.
1265
- if self . weak ( ) == 0 {
1266
- Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) ) ;
1276
+ if inner. weak ( ) == 0 {
1277
+ unsafe {
1278
+ Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) ) ;
1279
+ }
1267
1280
}
1268
1281
}
1269
1282
}
@@ -1284,7 +1297,9 @@ impl<T: ?Sized> Clone for Weak<T> {
1284
1297
/// ```
1285
1298
#[ inline]
1286
1299
fn clone ( & self ) -> Weak < T > {
1287
- self . inc_weak ( ) ;
1300
+ if let Some ( inner) = self . inner ( ) {
1301
+ inner. inc_weak ( )
1302
+ }
1288
1303
Weak { ptr : self . ptr }
1289
1304
}
1290
1305
}
@@ -1317,7 +1332,7 @@ impl<T> Default for Weak<T> {
1317
1332
}
1318
1333
}
1319
1334
1320
- // NOTE: We checked_add here to deal with mem::forget safety . In particular
1335
+ // NOTE: We checked_add here to deal with mem::forget safely . In particular
1321
1336
// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
1322
1337
// you can free the allocation while outstanding Rcs (or Weaks) exist.
1323
1338
// We abort because this is such a degenerate scenario that we don't care about
@@ -1370,12 +1385,10 @@ impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
1370
1385
}
1371
1386
}
1372
1387
1373
- impl < T : ?Sized > RcBoxPtr < T > for Weak < T > {
1388
+ impl < T : ?Sized > RcBoxPtr < T > for RcBox < T > {
1374
1389
#[ inline( always) ]
1375
1390
fn inner ( & self ) -> & RcBox < T > {
1376
- unsafe {
1377
- self . ptr . as_ref ( )
1378
- }
1391
+ self
1379
1392
}
1380
1393
}
1381
1394
0 commit comments