CloneToUninit: use a private specialization trait · patricklam/verify-rust-std@569ab6a (original) (raw)
`@@ -36,8 +36,7 @@
`
36
36
``
37
37
`#![stable(feature = "rust1", since = "1.0.0")]
`
38
38
``
39
``
`-
use crate::mem::{self, MaybeUninit};
`
40
``
`-
use crate::ptr;
`
``
39
`+
mod uninit;
`
41
40
``
42
41
`/// A common trait for the ability to explicitly duplicate an object.
`
43
42
`///
`
`@@ -248,7 +247,7 @@ pub unsafe trait CloneToUninit {
`
248
247
`` /// * dst
must be properly aligned.
``
249
248
`` /// * dst
must have the same [pointer metadata] (slice length or dyn
vtable) as self
.
``
250
249
`///
`
251
``
`-
/// [valid]: ptr#safety
`
``
250
`+
/// [valid]: crate::ptr#safety
`
252
251
`/// [pointer metadata]: crate::ptr::metadata()
`
253
252
`///
`
254
253
`/// # Panics
`
`@@ -272,83 +271,20 @@ pub unsafe trait CloneToUninit {
`
272
271
``
273
272
`#[unstable(feature = "clone_to_uninit", issue = "126799")]
`
274
273
`unsafe impl<T: Clone> CloneToUninit for T {
`
275
``
`-
#[inline]
`
276
``
`-
default unsafe fn clone_to_uninit(&self, dst: *mut Self) {
`
277
``
`-
// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of
`
278
``
`-
// ptr::write().
`
279
``
`-
unsafe {
`
280
``
`-
// We hope the optimizer will figure out to create the cloned value in-place,
`
281
``
`-
// skipping ever storing it on the stack and the copy to the destination.
`
282
``
`-
ptr::write(dst, self.clone());
`
283
``
`-
}
`
284
``
`-
}
`
285
``
`-
}
`
286
``
-
287
``
`` -
// Specialized implementation for types that are [Copy
], not just [Clone
],
``
288
``
`-
// and can therefore be copied bitwise.
`
289
``
`-
#[doc(hidden)]
`
290
``
`-
#[unstable(feature = "clone_to_uninit", issue = "126799")]
`
291
``
`-
unsafe impl<T: Copy> CloneToUninit for T {
`
292
274
`#[inline]
`
293
275
`unsafe fn clone_to_uninit(&self, dst: *mut Self) {
`
294
``
`-
// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of
`
295
``
`-
// ptr::copy_nonoverlapping().
`
296
``
`-
unsafe {
`
297
``
`-
ptr::copy_nonoverlapping(self, dst, 1);
`
298
``
`-
}
`
``
276
`+
// SAFETY: we're calling a specialization with the same contract
`
``
277
`+
unsafe { ::clone_one(self, dst) }
`
299
278
`}
`
300
279
`}
`
301
280
``
302
281
`#[unstable(feature = "clone_to_uninit", issue = "126799")]
`
303
282
`unsafe impl<T: Clone> CloneToUninit for [T] {
`
304
``
`-
#[inline]
`
305
``
`-
#[cfg_attr(debug_assertions, track_caller)]
`
306
``
`-
default unsafe fn clone_to_uninit(&self, dst: *mut Self) {
`
307
``
`-
let len = self.len();
`
308
``
`-
// This is the most likely mistake to make, so check it as a debug assertion.
`
309
``
`-
debug_assert_eq!(
`
310
``
`-
len,
`
311
``
`-
dst.len(),
`
312
``
`-
"clone_to_uninit() source and destination must have equal lengths",
`
313
``
`-
);
`
314
``
-
315
``
`` -
// SAFETY: The produced &mut
is valid because:
``
316
``
`-
// * The caller is obligated to provide a pointer which is valid for writes.
`
317
``
`-
// * All bytes pointed to are in MaybeUninit, so we don't care about the memory's
`
318
``
`-
// initialization status.
`
319
``
`-
let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit]) };
`
320
``
-
321
``
`-
// Copy the elements
`
322
``
`-
let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref);
`
323
``
`-
for element_ref in self.iter() {
`
324
``
`` -
// If the clone() panics, initializing
will take care of the cleanup.
``
325
``
`-
initializing.push(element_ref.clone());
`
326
``
`-
}
`
327
``
`-
// If we reach here, then the entire slice is initialized, and we've satisfied our
`
328
``
`-
// responsibilities to the caller. Disarm the cleanup guard by forgetting it.
`
329
``
`-
mem::forget(initializing);
`
330
``
`-
}
`
331
``
`-
}
`
332
``
-
333
``
`-
#[doc(hidden)]
`
334
``
`-
#[unstable(feature = "clone_to_uninit", issue = "126799")]
`
335
``
`-
unsafe impl<T: Copy> CloneToUninit for [T] {
`
336
283
`#[inline]
`
337
284
`#[cfg_attr(debug_assertions, track_caller)]
`
338
285
`unsafe fn clone_to_uninit(&self, dst: *mut Self) {
`
339
``
`-
let len = self.len();
`
340
``
`-
// This is the most likely mistake to make, so check it as a debug assertion.
`
341
``
`-
debug_assert_eq!(
`
342
``
`-
len,
`
343
``
`-
dst.len(),
`
344
``
`-
"clone_to_uninit() source and destination must have equal lengths",
`
345
``
`-
);
`
346
``
-
347
``
`-
// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of
`
348
``
`-
// ptr::copy_nonoverlapping().
`
349
``
`-
unsafe {
`
350
``
`-
ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len);
`
351
``
`-
}
`
``
286
`+
// SAFETY: we're calling a specialization with the same contract
`
``
287
`+
unsafe { ::clone_slice(self, dst) }
`
352
288
`}
`
353
289
`}
`
354
290
``
`@@ -374,53 +310,6 @@ unsafe impl CloneToUninit for crate::ffi::CStr {
`
374
310
`}
`
375
311
`}
`
376
312
``
377
``
`` -
/// Ownership of a collection of values stored in a non-owned [MaybeUninit<T>]
, some of which
``
378
``
`` -
/// are not yet initialized. This is sort of like a Vec
that doesn't own its allocation.
``
379
``
`-
/// Its responsibility is to provide cleanup on unwind by dropping the values that are
`
380
``
`-
/// initialized, unless disarmed by forgetting.
`
381
``
`-
///
`
382
``
`` -
/// This is a helper for impl<T: Clone> CloneToUninit for [T]
.
``
383
``
`-
struct InitializingSlice<'a, T> {
`
384
``
`-
data: &'a mut [MaybeUninit],
`
385
``
`` -
/// Number of elements of *self.data
that are initialized.
``
386
``
`-
initialized_len: usize,
`
387
``
`-
}
`
388
``
-
389
``
`-
impl<'a, T> InitializingSlice<'a, T> {
`
390
``
`-
#[inline]
`
391
``
`-
fn from_fully_uninit(data: &'a mut [MaybeUninit]) -> Self {
`
392
``
`-
Self { data, initialized_len: 0 }
`
393
``
`-
}
`
394
``
-
395
``
`-
/// Push a value onto the end of the initialized part of the slice.
`
396
``
`-
///
`
397
``
`-
/// # Panics
`
398
``
`-
///
`
399
``
`-
/// Panics if the slice is already fully initialized.
`
400
``
`-
#[inline]
`
401
``
`-
fn push(&mut self, value: T) {
`
402
``
`-
MaybeUninit::write(&mut self.data[self.initialized_len], value);
`
403
``
`-
self.initialized_len += 1;
`
404
``
`-
}
`
405
``
`-
}
`
406
``
-
407
``
`-
impl<'a, T> Drop for InitializingSlice<'a, T> {
`
408
``
`-
#[cold] // will only be invoked on unwind
`
409
``
`-
fn drop(&mut self) {
`
410
``
`-
let initialized_slice = ptr::slice_from_raw_parts_mut(
`
411
``
`-
MaybeUninit::slice_as_mut_ptr(self.data),
`
412
``
`-
self.initialized_len,
`
413
``
`-
);
`
414
``
`-
// SAFETY:
`
415
``
`-
// * the pointer is valid because it was made from a mutable reference
`
416
``
`` -
// * initialized_len
counts the initialized elements as an invariant of this type,
``
417
``
`-
// so each of the pointed-to elements is initialized and may be dropped.
`
418
``
`-
unsafe {
`
419
``
`-
ptr::drop_in_place::<[T]>(initialized_slice);
`
420
``
`-
}
`
421
``
`-
}
`
422
``
`-
}
`
423
``
-
424
313
`` /// Implementations of Clone
for primitive types.
``
425
314
`///
`
426
315
`/// Implementations that cannot be described in Rust
`