Add `core::clone::CloneToUninit`. · model-checking/verify-rust-std@a4ca461

@@ -36,6 +36,9 @@

36363737

#![stable(feature = "rust1", since = "1.0.0")]

383839+

use crate::mem::{self, MaybeUninit};

40+

use crate::ptr;

41+3942

/// A common trait for the ability to explicitly duplicate an object.

4043

///

4144

/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while

@@ -204,6 +207,189 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {

204207

_field: crate::marker::PhantomData<T>,

205208

}

206209210+

/// A generalization of [`Clone`] to dynamically-sized types stored in arbitrary containers.

211+

///

212+

/// This trait is implemented for all types implementing [`Clone`], and also [slices](slice) of all

213+

/// such types. You may also implement this trait to enable cloning trait objects and custom DSTs

214+

/// (structures containing dynamically-sized fields).

215+

///

216+

/// # Safety

217+

///

218+

/// Implementations must ensure that when `.clone_to_uninit(dst)` returns normally rather than

219+

/// panicking, it always leaves `*dst` initialized as a valid value of type `Self`.

220+

///

221+

/// # See also

222+

///

223+

/// * [`Clone::clone_from`] is a safe function which may be used instead when `Self` is a [`Sized`]

224+

/// and the destination is already initialized; it may be able to reuse allocations owned by

225+

/// the destination.

226+

/// * [`ToOwned`], which allocates a new destination container.

227+

///

228+

/// [`ToOwned`]: ../../std/borrow/trait.ToOwned.html

229+

#[unstable(feature = "clone_to_uninit", issue = "126799")]

230+

pub unsafe trait CloneToUninit {

231+

/// Performs copy-assignment from `self` to `dst`.

232+

///

233+

/// This is analogous to to `std::ptr::write(dst, self.clone())`,

234+

/// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)).

235+

///

236+

/// Before this function is called, `dst` may point to uninitialized memory.

237+

/// After this function is called, `dst` will point to initialized memory; it will be

238+

/// sound to create a `&Self` reference from the pointer.

239+

///

240+

/// # Safety

241+

///

242+

/// Behavior is undefined if any of the following conditions are violated:

243+

///

244+

/// * `dst` must be [valid] for writes.

245+

/// * `dst` must be properly aligned.

246+

/// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`.

247+

///

248+

/// [valid]: ptr#safety

249+

/// [pointer metadata]: crate::ptr::metadata()

250+

///

251+

/// # Panics

252+

///

253+

/// This function may panic. (For example, it might panic if memory allocation for a clone

254+

/// of a value owned by `self` fails.)

255+

/// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be

256+

/// read or dropped, because even if it was previously valid, it may have been partially

257+

/// overwritten.

258+

///

259+

/// The caller may also need to take care to deallocate the allocation pointed to by `dst`,

260+

/// if applicable, to avoid a memory leak, and may need to take other precautions to ensure

261+

/// soundness in the presence of unwinding.

262+

///

263+

/// Implementors should avoid leaking values by, upon unwinding, dropping all component values

264+

/// that might have already been created. (For example, if a `[Foo]` of length 3 is being

265+

/// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo`

266+

/// cloned should be dropped.)

267+

unsafe fn clone_to_uninit(&self, dst: *mut Self);

268+

}

269+270+

#[unstable(feature = "clone_to_uninit", issue = "126799")]

271+

unsafe impl<T: Clone> CloneToUninit for T {

272+

default unsafe fn clone_to_uninit(&self, dst: *mut Self) {

273+

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

274+

// ptr::write().

275+

unsafe {

276+

// We hope the optimizer will figure out to create the cloned value in-place,

277+

// skipping ever storing it on the stack and the copy to the destination.

278+

ptr::write(dst, self.clone());

279+

}

280+

}

281+

}

282+283+

// Specialized implementation for types that are [`Copy`], not just [`Clone`],

284+

// and can therefore be copied bitwise.

285+

#[unstable(feature = "clone_to_uninit", issue = "126799")]

286+

unsafe impl<T: Copy> CloneToUninit for T {

287+

unsafe fn clone_to_uninit(&self, dst: *mut Self) {

288+

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

289+

// ptr::copy_nonoverlapping().

290+

unsafe {

291+

ptr::copy_nonoverlapping(self, dst, 1);

292+

}

293+

}

294+

}

295+296+

#[unstable(feature = "clone_to_uninit", issue = "126799")]

297+

unsafe impl<T: Clone> CloneToUninit for [T] {

298+

#[cfg_attr(debug_assertions, track_caller)]

299+

default unsafe fn clone_to_uninit(&self, dst: *mut Self) {

300+

let len = self.len();

301+

// This is the most likely mistake to make, so check it as a debug assertion.

302+

debug_assert_eq!(

303+

len,

304+

dst.len(),

305+

"clone_to_uninit() source and destination must have equal lengths",

306+

);

307+308+

// SAFETY: The produced `&mut` is valid because:

309+

// * The caller is obligated to provide a pointer which is valid for writes.

310+

// * All bytes pointed to are in MaybeUninit, so we don't care about the memory's

311+

// initialization status.

312+

let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit<T>]) };

313+314+

// Copy the elements

315+

let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref);

316+

for element_ref in self.iter() {

317+

// If the clone() panics, `initializing` will take care of the cleanup.

318+

initializing.push(element_ref.clone());

319+

}

320+

// If we reach here, then the entire slice is initialized, and we've satisfied our

321+

// responsibilities to the caller. Disarm the cleanup guard by forgetting it.

322+

mem::forget(initializing);

323+

}

324+

}

325+326+

#[unstable(feature = "clone_to_uninit", issue = "126799")]

327+

unsafe impl<T: Copy> CloneToUninit for [T] {

328+

#[cfg_attr(debug_assertions, track_caller)]

329+

unsafe fn clone_to_uninit(&self, dst: *mut Self) {

330+

let len = self.len();

331+

// This is the most likely mistake to make, so check it as a debug assertion.

332+

debug_assert_eq!(

333+

len,

334+

dst.len(),

335+

"clone_to_uninit() source and destination must have equal lengths",

336+

);

337+338+

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

339+

// ptr::copy_nonoverlapping().

340+

unsafe {

341+

ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len);

342+

}

343+

}

344+

}

345+346+

/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which

347+

/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation.

348+

/// Its responsibility is to provide cleanup on unwind by dropping the values that *are*

349+

/// initialized, unless disarmed by forgetting.

350+

///

351+

/// This is a helper for `impl<T: Clone> CloneToUninit for [T]`.

352+

struct InitializingSlice<'a, T> {

353+

data: &'a mut [MaybeUninit<T>],

354+

/// Number of elements of `*self.data` that are initialized.

355+

initialized_len: usize,

356+

}

357+358+

impl<'a, T> InitializingSlice<'a, T> {

359+

#[inline]

360+

fn from_fully_uninit(data: &'a mut [MaybeUninit<T>]) -> Self {

361+

Self { data, initialized_len: 0 }

362+

}

363+364+

/// Push a value onto the end of the initialized part of the slice.

365+

///

366+

/// # Panics

367+

///

368+

/// Panics if the slice is already fully initialized.

369+

#[inline]

370+

fn push(&mut self, value: T) {

371+

MaybeUninit::write(&mut self.data[self.initialized_len], value);

372+

self.initialized_len += 1;

373+

}

374+

}

375+376+

impl<'a, T> Drop for InitializingSlice<'a, T> {

377+

#[cold] // will only be invoked on unwind

378+

fn drop(&mut self) {

379+

let initialized_slice = ptr::slice_from_raw_parts_mut(

380+

MaybeUninit::slice_as_mut_ptr(self.data),

381+

self.initialized_len,

382+

);

383+

// SAFETY:

384+

// * the pointer is valid because it was made from a mutable reference

385+

// * `initialized_len` counts the initialized elements as an invariant of this type,

386+

// so each of the pointed-to elements is initialized and may be dropped.

387+

unsafe {

388+

ptr::drop_in_place::<[T]>(initialized_slice);

389+

}

390+

}

391+

}

392+207393

/// Implementations of `Clone` for primitive types.

208394

///

209395

/// Implementations that cannot be described in Rust