Auto merge of #116113 - kpreid:arcmut, r=dtolnay · model-checking/verify-rust-std@e1edea8 (original) (raw)

`@@ -249,6 +249,8 @@ use std::boxed::Box;

`

249

249

`use core::any::Any;

`

250

250

`use core::borrow;

`

251

251

`use core::cell::Cell;

`

``

252

`+

#[cfg(not(no_global_oom_handling))]

`

``

253

`+

use core::clone::CloneToUninit;

`

252

254

`use core::cmp::Ordering;

`

253

255

`use core::fmt;

`

254

256

`use core::hash::{Hash, Hasher};

`

`@@ -268,8 +270,6 @@ use core::slice::from_raw_parts_mut;

`

268

270

``

269

271

`#[cfg(not(no_global_oom_handling))]

`

270

272

`use crate::alloc::handle_alloc_error;

`

271

``

`-

#[cfg(not(no_global_oom_handling))]

`

272

``

`-

use crate::alloc::WriteCloneIntoRaw;

`

273

273

`use crate::alloc::{AllocError, Allocator, Global, Layout};

`

274

274

`use crate::borrow::{Cow, ToOwned};

`

275

275

`#[cfg(not(no_global_oom_handling))]

`

`@@ -1749,7 +1749,8 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {

`

1749

1749

`}

`

1750

1750

`}

`

1751

1751

``

1752

``

`-

impl<T: Clone, A: Allocator + Clone> Rc<T, A> {

`

``

1752

`+

#[cfg(not(no_global_oom_handling))]

`

``

1753

`+

impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Rc<T, A> {

`

1753

1754

`` /// Makes a mutable reference into the given Rc.

``

1754

1755

`///

`

1755

1756

`` /// If there are other Rc pointers to the same allocation, then make_mut will

``

`@@ -1800,31 +1801,52 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {

`

1800

1801

`/// assert!(76 == *data);

`

1801

1802

`/// assert!(weak.upgrade().is_none());

`

1802

1803

```` /// ```

````

1803

``

`-

#[cfg(not(no_global_oom_handling))]

`

1804

1804

`#[inline]

`

1805

1805

`#[stable(feature = "rc_unique", since = "1.4.0")]

`

1806

1806

`pub fn make_mut(this: &mut Self) -> &mut T {

`

``

1807

`+

let size_of_val = size_of_val::(&**this);

`

``

1808

+

1807

1809

`if Rc::strong_count(this) != 1 {

`

1808

1810

`// Gotta clone the data, there are other Rcs.

`

1809

``

`-

// Pre-allocate memory to allow writing the cloned value directly.

`

1810

``

`-

let mut rc = Self::new_uninit_in(this.alloc.clone());

`

1811

``

`-

unsafe {

`

1812

``

`-

let data = Rc::get_mut_unchecked(&mut rc);

`

1813

``

`-

(**this).write_clone_into_raw(data.as_mut_ptr());

`

1814

``

`-

*this = rc.assume_init();

`

1815

``

`-

}

`

``

1811

+

``

1812

`+

let this_data_ref: &T = &**this;

`

``

1813

`` +

// in_progress drops the allocation if we panic before finishing initializing it.

``

``

1814

`+

let mut in_progress: UniqueRcUninit<T, A> =

`

``

1815

`+

UniqueRcUninit::new(this_data_ref, this.alloc.clone());

`

``

1816

+

``

1817

`+

// Initialize with clone of this.

`

``

1818

`+

let initialized_clone = unsafe {

`

``

1819

`` +

// Clone. If the clone panics, in_progress will be dropped and clean up.

``

``

1820

`+

this_data_ref.clone_to_uninit(in_progress.data_ptr());

`

``

1821

`+

// Cast type of pointer, now that it is initialized.

`

``

1822

`+

in_progress.into_rc()

`

``

1823

`+

};

`

``

1824

+

``

1825

`` +

// Replace this with newly constructed Rc.

``

``

1826

`+

*this = initialized_clone;

`

1816

1827

`} else if Rc::weak_count(this) != 0 {

`

1817

1828

`// Can just steal the data, all that's left is Weaks

`

1818

``

`-

let mut rc = Self::new_uninit_in(this.alloc.clone());

`

``

1829

+

``

1830

`+

// We don't need panic-protection like the above branch does, but we might as well

`

``

1831

`+

// use the same mechanism.

`

``

1832

`+

let mut in_progress: UniqueRcUninit<T, A> =

`

``

1833

`+

UniqueRcUninit::new(&**this, this.alloc.clone());

`

1819

1834

`unsafe {

`

1820

``

`-

let data = Rc::get_mut_unchecked(&mut rc);

`

1821

``

`-

data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);

`

``

1835

`` +

// Initialize in_progress with move of **this.

``

``

1836

`` +

// We have to express this in terms of bytes because T: ?Sized; there is no

``

``

1837

`` +

// operation that just copies a value based on its size_of_val().

``

``

1838

`+

ptr::copy_nonoverlapping(

`

``

1839

`+

ptr::from_ref(&**this).cast::(),

`

``

1840

`+

in_progress.data_ptr().cast::(),

`

``

1841

`+

size_of_val,

`

``

1842

`+

);

`

1822

1843

``

1823

1844

` this.inner().dec_strong();

`

1824

1845

`// Remove implicit strong-weak ref (no need to craft a fake

`

1825

1846

`// Weak here -- we know other Weaks can clean up for us)

`

1826

1847

` this.inner().dec_weak();

`

1827

``

`-

ptr::write(this, rc.assume_init());

`

``

1848

`` +

// Replace this with newly constructed Rc that has the moved data.

``

``

1849

`+

ptr::write(this, in_progress.into_rc());

`

1828

1850

`}

`

1829

1851

`}

`

1830

1852

`// This unsafety is ok because we're guaranteed that the pointer

`

`@@ -3686,3 +3708,67 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {

`

3686

3708

`}

`

3687

3709

`}

`

3688

3710

`}

`

``

3711

+

``

3712

`` +

/// A unique owning pointer to a [RcBox] that does not imply the contents are initialized,

``

``

3713

`+

/// but will deallocate it (without dropping the value) when dropped.

`

``

3714

`+

///

`

``

3715

`` +

/// This is a helper for [Rc::make_mut()] to ensure correct cleanup on panic.

``

``

3716

`` +

/// It is nearly a duplicate of UniqueRc<MaybeUninit<T>, A> except that it allows T: !Sized,

``

``

3717

`` +

/// which MaybeUninit does not.

``

``

3718

`+

#[cfg(not(no_global_oom_handling))]

`

``

3719

`+

struct UniqueRcUninit<T: ?Sized, A: Allocator> {

`

``

3720

`+

ptr: NonNull<RcBox>,

`

``

3721

`+

layout_for_value: Layout,

`

``

3722

`+

alloc: Option,

`

``

3723

`+

}

`

``

3724

+

``

3725

`+

#[cfg(not(no_global_oom_handling))]

`

``

3726

`+

impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {

`

``

3727

`` +

/// Allocate a RcBox with layout suitable to contain for_value or a clone of it.

``

``

3728

`+

fn new(for_value: &T, alloc: A) -> UniqueRcUninit<T, A> {

`

``

3729

`+

let layout = Layout::for_value(for_value);

`

``

3730

`+

let ptr = unsafe {

`

``

3731

`+

Rc::allocate_for_layout(

`

``

3732

`+

layout,

`

``

3733

`+

|layout_for_rcbox| alloc.allocate(layout_for_rcbox),

`

``

3734

`+

|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcBox),

`

``

3735

`+

)

`

``

3736

`+

};

`

``

3737

`+

Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }

`

``

3738

`+

}

`

``

3739

+

``

3740

`` +

/// Returns the pointer to be written into to initialize the [Rc].

``

``

3741

`+

fn data_ptr(&mut self) -> *mut T {

`

``

3742

`+

let offset = data_offset_align(self.layout_for_value.align());

`

``

3743

`+

unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T }

`

``

3744

`+

}

`

``

3745

+

``

3746

`` +

/// Upgrade this into a normal [Rc].

``

``

3747

`+

///

`

``

3748

`+

/// # Safety

`

``

3749

`+

///

`

``

3750

`` +

/// The data must have been initialized (by writing to [Self::data_ptr()]).

``

``

3751

`+

unsafe fn into_rc(mut self) -> Rc<T, A> {

`

``

3752

`+

let ptr = self.ptr;

`

``

3753

`+

let alloc = self.alloc.take().unwrap();

`

``

3754

`+

mem::forget(self);

`

``

3755

`` +

// SAFETY: The pointer is valid as per UniqueRcUninit::new, and the caller is responsible

``

``

3756

`+

// for having initialized the data.

`

``

3757

`+

unsafe { Rc::from_ptr_in(ptr.as_ptr(), alloc) }

`

``

3758

`+

}

`

``

3759

`+

}

`

``

3760

+

``

3761

`+

#[cfg(not(no_global_oom_handling))]

`

``

3762

`+

impl<T: ?Sized, A: Allocator> Drop for UniqueRcUninit<T, A> {

`

``

3763

`+

fn drop(&mut self) {

`

``

3764

`+

// SAFETY:

`

``

3765

`+

// * new() produced a pointer safe to deallocate.

`

``

3766

`+

// * We own the pointer unless into_rc() was called, which forgets us.

`

``

3767

`+

unsafe {

`

``

3768

`+

self.alloc

`

``

3769

`+

.take()

`

``

3770

`+

.unwrap()

`

``

3771

`+

.deallocate(self.ptr.cast(), rcbox_layout_for_value_layout(self.layout_for_value));

`

``

3772

`+

}

`

``

3773

`+

}

`

``

3774

`+

}

`