Skip to content

Commit 3af372a

Browse files
authored
Rollup merge of rust-lang#52637 - RalfJung:rc, r=joshtriplett
Don't use NonNull::dangling as sentinel value in Rc, Arc Instead, rely on alignment and use usize::MAX as sentinel. Cc rust-lang#52508 r? @joshtriplett
2 parents 4084f0e + a303741 commit 3af372a

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

src/liballoc/rc.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ use core::ops::Deref;
258258
use core::ops::CoerceUnsized;
259259
use core::ptr::{self, NonNull};
260260
use core::convert::From;
261+
use core::usize;
261262

262263
use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
263264
use string::String;
@@ -449,6 +450,8 @@ impl<T: ?Sized> Rc<T> {
449450
#[stable(feature = "rc_weak", since = "1.4.0")]
450451
pub fn downgrade(this: &Self) -> Weak<T> {
451452
this.inc_weak();
453+
// Make sure we do not create a dangling Weak
454+
debug_assert!(!is_dangling(this.ptr));
452455
Weak { ptr: this.ptr }
453456
}
454457

@@ -1154,8 +1157,9 @@ impl<T> From<Vec<T>> for Rc<[T]> {
11541157
pub struct Weak<T: ?Sized> {
11551158
// This is a `NonNull` to allow optimizing the size of this type in enums,
11561159
// but it is not necessarily a valid pointer.
1157-
// `Weak::new` sets this to a dangling pointer so that it doesn’t need
1158-
// to allocate space on the heap.
1160+
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
1161+
// to allocate space on the heap. That's not a value a real pointer
1162+
// will ever have because RcBox has alignment at least 2.
11591163
ptr: NonNull<RcBox<T>>,
11601164
}
11611165

@@ -1185,15 +1189,14 @@ impl<T> Weak<T> {
11851189
#[stable(feature = "downgraded_weak", since = "1.10.0")]
11861190
pub fn new() -> Weak<T> {
11871191
Weak {
1188-
ptr: NonNull::dangling(),
1192+
ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
11891193
}
11901194
}
11911195
}
11921196

11931197
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
11941198
let address = ptr.as_ptr() as *mut () as usize;
1195-
let align = align_of_val(unsafe { ptr.as_ref() });
1196-
address == align
1199+
address == usize::MAX
11971200
}
11981201

11991202
impl<T: ?Sized> Weak<T> {

src/liballoc/sync.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
238238
pub struct Weak<T: ?Sized> {
239239
// This is a `NonNull` to allow optimizing the size of this type in enums,
240240
// but it is not necessarily a valid pointer.
241-
// `Weak::new` sets this to a dangling pointer so that it doesn’t need
242-
// to allocate space on the heap.
241+
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
242+
// to allocate space on the heap. That's not a value a real pointer
243+
// will ever have because RcBox has alignment at least 2.
243244
ptr: NonNull<ArcInner<T>>,
244245
}
245246

@@ -442,7 +443,11 @@ impl<T: ?Sized> Arc<T> {
442443
// synchronize with the write coming from `is_unique`, so that the
443444
// events prior to that write happen before this read.
444445
match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) {
445-
Ok(_) => return Weak { ptr: this.ptr },
446+
Ok(_) => {
447+
// Make sure we do not create a dangling Weak
448+
debug_assert!(!is_dangling(this.ptr));
449+
return Weak { ptr: this.ptr };
450+
}
446451
Err(old) => cur = old,
447452
}
448453
}
@@ -1033,7 +1038,7 @@ impl<T> Weak<T> {
10331038
#[stable(feature = "downgraded_weak", since = "1.10.0")]
10341039
pub fn new() -> Weak<T> {
10351040
Weak {
1036-
ptr: NonNull::dangling(),
1041+
ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
10371042
}
10381043
}
10391044
}

0 commit comments

Comments
 (0)