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