Add core::clone::CloneToUninit
. · rust-lang/rust@ec201b8 (original) (raw)
`@@ -36,6 +36,9 @@
`
36
36
``
37
37
`#![stable(feature = "rust1", since = "1.0.0")]
`
38
38
``
``
39
`+
use crate::mem::{self, MaybeUninit};
`
``
40
`+
use crate::ptr;
`
``
41
+
39
42
`/// A common trait for the ability to explicitly duplicate an object.
`
40
43
`///
`
41
44
`` /// 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> {
`
204
207
`_field: crate:📑:PhantomData,
`
205
208
`}
`
206
209
``
``
210
`` +
/// 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 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
).
``
``
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]) };
`
``
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],
`
``
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]) -> 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
+
207
393
`` /// Implementations of Clone
for primitive types.
``
208
394
`///
`
209
395
`/// Implementations that cannot be described in Rust
`