@@ -253,14 +253,15 @@ use core::hash::{Hash, Hasher};
253253use core:: intrinsics:: abort;
254254use core:: marker;
255255use 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} ;
257257use core:: ops:: Deref ;
258258use core:: ops:: CoerceUnsized ;
259259use core:: ptr:: { self , NonNull } ;
260260use core:: convert:: From ;
261261
262262use alloc:: { Global , Alloc , Layout , box_free, handle_alloc_error} ;
263263use string:: String ;
264+ use sync:: is_dangling;
264265use vec:: Vec ;
265266
266267struct RcBox < T : ?Sized > {
@@ -1153,6 +1154,10 @@ impl<T> From<Vec<T>> for Rc<[T]> {
11531154/// [`None`]: ../../std/option/enum.Option.html#variant.None
11541155#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
11551156pub 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.
11561161 ptr : NonNull < RcBox < T > > ,
11571162}
11581163
@@ -1165,8 +1170,8 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
11651170impl < T : ?Sized + Unsize < U > , U : ?Sized > CoerceUnsized < Weak < U > > for Weak < T > { }
11661171
11671172impl < 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`].
11701175 ///
11711176 /// [`upgrade`]: struct.Weak.html#method.upgrade
11721177 /// [`None`]: ../../std/option/enum.Option.html
@@ -1181,14 +1186,8 @@ impl<T> Weak<T> {
11811186 /// ```
11821187 #[ stable( feature = "downgraded_weak" , since = "1.10.0" ) ]
11831188 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 ( ) ,
11921191 }
11931192 }
11941193}
@@ -1222,13 +1221,25 @@ impl<T: ?Sized> Weak<T> {
12221221 /// ```
12231222 #[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
12241223 pub fn upgrade ( & self ) -> Option < Rc < T > > {
1225- if self . strong ( ) == 0 {
1224+ let inner = self . inner ( ) ?;
1225+ if inner. strong ( ) == 0 {
12261226 None
12271227 } else {
1228- self . inc_strong ( ) ;
1228+ inner . inc_strong ( ) ;
12291229 Some ( Rc { ptr : self . ptr , phantom : PhantomData } )
12301230 }
12311231 }
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+ }
12321243}
12331244
12341245#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
@@ -1258,12 +1269,14 @@ impl<T: ?Sized> Drop for Weak<T> {
12581269 /// assert!(other_weak_foo.upgrade().is_none());
12591270 /// ```
12601271 fn drop ( & mut self ) {
1261- unsafe {
1262- self . dec_weak ( ) ;
1272+ if let Some ( inner ) = self . inner ( ) {
1273+ inner . dec_weak ( ) ;
12631274 // the weak count starts at 1, and will only go to zero if all
12641275 // 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+ }
12671280 }
12681281 }
12691282 }
@@ -1284,7 +1297,9 @@ impl<T: ?Sized> Clone for Weak<T> {
12841297 /// ```
12851298 #[ inline]
12861299 fn clone ( & self ) -> Weak < T > {
1287- self . inc_weak ( ) ;
1300+ if let Some ( inner) = self . inner ( ) {
1301+ inner. inc_weak ( )
1302+ }
12881303 Weak { ptr : self . ptr }
12891304 }
12901305}
@@ -1317,7 +1332,7 @@ impl<T> Default for Weak<T> {
13171332 }
13181333}
13191334
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
13211336// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
13221337// you can free the allocation while outstanding Rcs (or Weaks) exist.
13231338// 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> {
13701385 }
13711386}
13721387
1373- impl < T : ?Sized > RcBoxPtr < T > for Weak < T > {
1388+ impl < T : ?Sized > RcBoxPtr < T > for RcBox < T > {
13741389 #[ inline( always) ]
13751390 fn inner ( & self ) -> & RcBox < T > {
1376- unsafe {
1377- self . ptr . as_ref ( )
1378- }
1391+ self
13791392 }
13801393}
13811394
0 commit comments