Skip to content

Commit 2d6cbd2

Browse files
committed
Auto merge of rust-lang#76637 - RalfJung:rollup-eaykf93, r=RalfJung
Rollup of 7 pull requests Successful merges: - rust-lang#76114 (Add saturating methods for `Duration`) - rust-lang#76297 (rustdoc: fix min_const_generics with ty::Param) - rust-lang#76484 (Add MaybeUninit::assume_init_drop.) - rust-lang#76530 (Eliminate mut reference UB in Drop impl for Rc<T>) - rust-lang#76583 (Update `std::os` module documentation.) - rust-lang#76599 (Finish off revisions for const generics UI tests.) - rust-lang#76615 (Add missing examples on binary core traits) Failed merges: r? `@ghost`
2 parents 2e2e7de + 0ed4bc5 commit 2d6cbd2

29 files changed

+488
-94
lines changed

library/alloc/src/rc.rs

+75-38
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
295295
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
296296

297297
impl<T: ?Sized> Rc<T> {
298+
#[inline(always)]
299+
fn inner(&self) -> &RcBox<T> {
300+
// This unsafety is ok because while this Rc is alive we're guaranteed
301+
// that the inner pointer is valid.
302+
unsafe { self.ptr.as_ref() }
303+
}
304+
298305
fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
299306
Self { ptr, phantom: PhantomData }
300307
}
@@ -469,7 +476,7 @@ impl<T> Rc<T> {
469476
// the strong count, and then remove the implicit "strong weak"
470477
// pointer while also handling drop logic by just crafting a
471478
// fake Weak.
472-
this.dec_strong();
479+
this.inner().dec_strong();
473480
let _weak = Weak { ptr: this.ptr };
474481
forget(this);
475482
Ok(val)
@@ -735,7 +742,7 @@ impl<T: ?Sized> Rc<T> {
735742
/// ```
736743
#[stable(feature = "rc_weak", since = "1.4.0")]
737744
pub fn downgrade(this: &Self) -> Weak<T> {
738-
this.inc_weak();
745+
this.inner().inc_weak();
739746
// Make sure we do not create a dangling Weak
740747
debug_assert!(!is_dangling(this.ptr));
741748
Weak { ptr: this.ptr }
@@ -756,7 +763,7 @@ impl<T: ?Sized> Rc<T> {
756763
#[inline]
757764
#[stable(feature = "rc_counts", since = "1.15.0")]
758765
pub fn weak_count(this: &Self) -> usize {
759-
this.weak() - 1
766+
this.inner().weak() - 1
760767
}
761768

762769
/// Gets the number of strong (`Rc`) pointers to this allocation.
@@ -774,7 +781,7 @@ impl<T: ?Sized> Rc<T> {
774781
#[inline]
775782
#[stable(feature = "rc_counts", since = "1.15.0")]
776783
pub fn strong_count(this: &Self) -> usize {
777-
this.strong()
784+
this.inner().strong()
778785
}
779786

780787
/// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
@@ -844,7 +851,9 @@ impl<T: ?Sized> Rc<T> {
844851
#[inline]
845852
#[unstable(feature = "get_mut_unchecked", issue = "63292")]
846853
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
847-
unsafe { &mut this.ptr.as_mut().value }
854+
// We are careful to *not* create a reference covering the "count" fields, as
855+
// this would conflict with accesses to the reference counts (e.g. by `Weak`).
856+
unsafe { &mut (*this.ptr.as_ptr()).value }
848857
}
849858

850859
#[inline]
@@ -931,10 +940,10 @@ impl<T: Clone> Rc<T> {
931940
unsafe {
932941
let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value));
933942
mem::swap(this, &mut swap);
934-
swap.dec_strong();
943+
swap.inner().dec_strong();
935944
// Remove implicit strong-weak ref (no need to craft a fake
936945
// Weak here -- we know other Weaks can clean up for us)
937-
swap.dec_weak();
946+
swap.inner().dec_weak();
938947
forget(swap);
939948
}
940949
}
@@ -1192,16 +1201,16 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
11921201
/// ```
11931202
fn drop(&mut self) {
11941203
unsafe {
1195-
self.dec_strong();
1196-
if self.strong() == 0 {
1204+
self.inner().dec_strong();
1205+
if self.inner().strong() == 0 {
11971206
// destroy the contained object
1198-
ptr::drop_in_place(self.ptr.as_mut());
1207+
ptr::drop_in_place(Self::get_mut_unchecked(self));
11991208

12001209
// remove the implicit "strong weak" pointer now that we've
12011210
// destroyed the contents.
1202-
self.dec_weak();
1211+
self.inner().dec_weak();
12031212

1204-
if self.weak() == 0 {
1213+
if self.inner().weak() == 0 {
12051214
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()));
12061215
}
12071216
}
@@ -1227,7 +1236,7 @@ impl<T: ?Sized> Clone for Rc<T> {
12271236
/// ```
12281237
#[inline]
12291238
fn clone(&self) -> Rc<T> {
1230-
self.inc_strong();
1239+
self.inner().inc_strong();
12311240
Self::from_inner(self.ptr)
12321241
}
12331242
}
@@ -1851,6 +1860,13 @@ pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
18511860
address == usize::MAX
18521861
}
18531862

1863+
/// Helper type to allow accessing the reference counts without
1864+
/// making any assertions about the data field.
1865+
struct WeakInner<'a> {
1866+
weak: &'a Cell<usize>,
1867+
strong: &'a Cell<usize>,
1868+
}
1869+
18541870
impl<T: ?Sized> Weak<T> {
18551871
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
18561872
/// dropping of the inner value if successful.
@@ -1910,11 +1926,21 @@ impl<T: ?Sized> Weak<T> {
19101926
.unwrap_or(0)
19111927
}
19121928

1913-
/// Returns `None` when the pointer is dangling and there is no allocated `RcBox`
1929+
/// Returns `None` when the pointer is dangling and there is no allocated `RcBox`,
19141930
/// (i.e., when this `Weak` was created by `Weak::new`).
19151931
#[inline]
1916-
fn inner(&self) -> Option<&RcBox<T>> {
1917-
if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) }
1932+
fn inner(&self) -> Option<WeakInner<'_>> {
1933+
if is_dangling(self.ptr) {
1934+
None
1935+
} else {
1936+
// We are careful to *not* create a reference covering the "data" field, as
1937+
// the field may be mutated concurrently (for example, if the last `Rc`
1938+
// is dropped, the data field will be dropped in-place).
1939+
Some(unsafe {
1940+
let ptr = self.ptr.as_ptr();
1941+
WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak }
1942+
})
1943+
}
19181944
}
19191945

19201946
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
@@ -1992,14 +2018,14 @@ impl<T: ?Sized> Drop for Weak<T> {
19922018
/// assert!(other_weak_foo.upgrade().is_none());
19932019
/// ```
19942020
fn drop(&mut self) {
1995-
if let Some(inner) = self.inner() {
1996-
inner.dec_weak();
1997-
// the weak count starts at 1, and will only go to zero if all
1998-
// the strong pointers have disappeared.
1999-
if inner.weak() == 0 {
2000-
unsafe {
2001-
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()));
2002-
}
2021+
let inner = if let Some(inner) = self.inner() { inner } else { return };
2022+
2023+
inner.dec_weak();
2024+
// the weak count starts at 1, and will only go to zero if all
2025+
// the strong pointers have disappeared.
2026+
if inner.weak() == 0 {
2027+
unsafe {
2028+
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()));
20032029
}
20042030
}
20052031
}
@@ -2065,12 +2091,13 @@ impl<T> Default for Weak<T> {
20652091
// clone these much in Rust thanks to ownership and move-semantics.
20662092

20672093
#[doc(hidden)]
2068-
trait RcBoxPtr<T: ?Sized> {
2069-
fn inner(&self) -> &RcBox<T>;
2094+
trait RcInnerPtr {
2095+
fn weak_ref(&self) -> &Cell<usize>;
2096+
fn strong_ref(&self) -> &Cell<usize>;
20702097

20712098
#[inline]
20722099
fn strong(&self) -> usize {
2073-
self.inner().strong.get()
2100+
self.strong_ref().get()
20742101
}
20752102

20762103
#[inline]
@@ -2084,17 +2111,17 @@ trait RcBoxPtr<T: ?Sized> {
20842111
if strong == 0 || strong == usize::MAX {
20852112
abort();
20862113
}
2087-
self.inner().strong.set(strong + 1);
2114+
self.strong_ref().set(strong + 1);
20882115
}
20892116

20902117
#[inline]
20912118
fn dec_strong(&self) {
2092-
self.inner().strong.set(self.strong() - 1);
2119+
self.strong_ref().set(self.strong() - 1);
20932120
}
20942121

20952122
#[inline]
20962123
fn weak(&self) -> usize {
2097-
self.inner().weak.get()
2124+
self.weak_ref().get()
20982125
}
20992126

21002127
#[inline]
@@ -2108,26 +2135,36 @@ trait RcBoxPtr<T: ?Sized> {
21082135
if weak == 0 || weak == usize::MAX {
21092136
abort();
21102137
}
2111-
self.inner().weak.set(weak + 1);
2138+
self.weak_ref().set(weak + 1);
21122139
}
21132140

21142141
#[inline]
21152142
fn dec_weak(&self) {
2116-
self.inner().weak.set(self.weak() - 1);
2143+
self.weak_ref().set(self.weak() - 1);
21172144
}
21182145
}
21192146

2120-
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
2147+
impl<T: ?Sized> RcInnerPtr for RcBox<T> {
21212148
#[inline(always)]
2122-
fn inner(&self) -> &RcBox<T> {
2123-
unsafe { self.ptr.as_ref() }
2149+
fn weak_ref(&self) -> &Cell<usize> {
2150+
&self.weak
2151+
}
2152+
2153+
#[inline(always)]
2154+
fn strong_ref(&self) -> &Cell<usize> {
2155+
&self.strong
21242156
}
21252157
}
21262158

2127-
impl<T: ?Sized> RcBoxPtr<T> for RcBox<T> {
2159+
impl<'a> RcInnerPtr for WeakInner<'a> {
21282160
#[inline(always)]
2129-
fn inner(&self) -> &RcBox<T> {
2130-
self
2161+
fn weak_ref(&self) -> &Cell<usize> {
2162+
self.weak
2163+
}
2164+
2165+
#[inline(always)]
2166+
fn strong_ref(&self) -> &Cell<usize> {
2167+
self.strong
21312168
}
21322169
}
21332170

library/core/src/array/iter.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
103103
// dead now (i.e. do not touch). As `idx` was the start of the
104104
// alive-zone, the alive zone is now `data[alive]` again, restoring
105105
// all invariants.
106-
unsafe { self.data.get_unchecked(idx).read() }
106+
unsafe { self.data.get_unchecked(idx).assume_init_read() }
107107
})
108108
}
109109

@@ -136,7 +136,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
136136
// dead now (i.e. do not touch). As `idx` was the end of the
137137
// alive-zone, the alive zone is now `data[alive]` again, restoring
138138
// all invariants.
139-
unsafe { self.data.get_unchecked(idx).read() }
139+
unsafe { self.data.get_unchecked(idx).assume_init_read() }
140140
})
141141
}
142142
}

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#![feature(doc_cfg)]
101101
#![feature(doc_spotlight)]
102102
#![feature(duration_consts_2)]
103+
#![feature(duration_saturating_ops)]
103104
#![feature(extern_types)]
104105
#![feature(fundamental)]
105106
#![feature(intrinsics)]

library/core/src/mem/maybe_uninit.rs

+40-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::any::type_name;
22
use crate::fmt;
33
use crate::intrinsics;
44
use crate::mem::ManuallyDrop;
5+
use crate::ptr;
56

67
/// A wrapper type to construct uninitialized instances of `T`.
78
///
@@ -471,6 +472,8 @@ impl<T> MaybeUninit<T> {
471472
/// *immediate* undefined behavior, but will cause undefined behavior with most
472473
/// safe operations (including dropping it).
473474
///
475+
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
476+
///
474477
/// # Examples
475478
///
476479
/// Correct usage of this method:
@@ -519,8 +522,8 @@ impl<T> MaybeUninit<T> {
519522
/// this initialization invariant.
520523
///
521524
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
522-
/// multiple copies of the data (by calling `read` multiple times, or first
523-
/// calling `read` and then [`assume_init`]), it is your responsibility
525+
/// multiple copies of the data (by calling `assume_init_read` multiple times, or first
526+
/// calling `assume_init_read` and then [`assume_init`]), it is your responsibility
524527
/// to ensure that that data may indeed be duplicated.
525528
///
526529
/// [inv]: #initialization-invariant
@@ -536,16 +539,16 @@ impl<T> MaybeUninit<T> {
536539
///
537540
/// let mut x = MaybeUninit::<u32>::uninit();
538541
/// x.write(13);
539-
/// let x1 = unsafe { x.read() };
542+
/// let x1 = unsafe { x.assume_init_read() };
540543
/// // `u32` is `Copy`, so we may read multiple times.
541-
/// let x2 = unsafe { x.read() };
544+
/// let x2 = unsafe { x.assume_init_read() };
542545
/// assert_eq!(x1, x2);
543546
///
544547
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
545548
/// x.write(None);
546-
/// let x1 = unsafe { x.read() };
549+
/// let x1 = unsafe { x.assume_init_read() };
547550
/// // Duplicating a `None` value is okay, so we may read multiple times.
548-
/// let x2 = unsafe { x.read() };
551+
/// let x2 = unsafe { x.assume_init_read() };
549552
/// assert_eq!(x1, x2);
550553
/// ```
551554
///
@@ -557,14 +560,14 @@ impl<T> MaybeUninit<T> {
557560
///
558561
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
559562
/// x.write(Some(vec![0,1,2]));
560-
/// let x1 = unsafe { x.read() };
561-
/// let x2 = unsafe { x.read() };
563+
/// let x1 = unsafe { x.assume_init_read() };
564+
/// let x2 = unsafe { x.assume_init_read() };
562565
/// // We now created two copies of the same vector, leading to a double-free ⚠️ when
563566
/// // they both get dropped!
564567
/// ```
565568
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
566569
#[inline(always)]
567-
pub unsafe fn read(&self) -> T {
570+
pub unsafe fn assume_init_read(&self) -> T {
568571
// SAFETY: the caller must guarantee that `self` is initialized.
569572
// Reading from `self.as_ptr()` is safe since `self` should be initialized.
570573
unsafe {
@@ -573,6 +576,34 @@ impl<T> MaybeUninit<T> {
573576
}
574577
}
575578

579+
/// Drops the contained value in place.
580+
///
581+
/// If you have ownership of the `MaybeUninit`, you can use [`assume_init`] instead.
582+
///
583+
/// # Safety
584+
///
585+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is
586+
/// in an initialized state. Calling this when the content is not yet fully
587+
/// initialized causes undefined behavior.
588+
///
589+
/// On top of that, all additional invariants of the type `T` must be
590+
/// satisfied, as the `Drop` implementation of `T` (or its members) may
591+
/// rely on this. For example, a `1`-initialized [`Vec<T>`] is considered
592+
/// initialized (under the current implementation; this does not constitute
593+
/// a stable guarantee) because the only requirement the compiler knows
594+
/// about it is that the data pointer must be non-null. Dropping such a
595+
/// `Vec<T>` however will cause undefined behaviour.
596+
///
597+
/// [`assume_init`]: MaybeUninit::assume_init
598+
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
599+
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
600+
pub unsafe fn assume_init_drop(&mut self) {
601+
// SAFETY: the caller must guarantee that `self` is initialized and
602+
// satisfies all invariants of `T`.
603+
// Dropping the value in place is safe if that is the case.
604+
unsafe { ptr::drop_in_place(self.as_mut_ptr()) }
605+
}
606+
576607
/// Gets a shared reference to the contained value.
577608
///
578609
/// This can be useful when we want to access a `MaybeUninit` that has been

0 commit comments

Comments
 (0)