3636
3737#![ stable( feature = "rust1" , since = "1.0.0" ) ]
3838
39- use crate :: mem:: { self , MaybeUninit } ;
40- use crate :: ptr;
39+ mod uninit;
4140
4241/// A common trait for the ability to explicitly duplicate an object.
4342///
@@ -248,7 +247,7 @@ pub unsafe trait CloneToUninit {
248247 /// * `dst` must be properly aligned.
249248 /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`.
250249 ///
251- /// [valid]: ptr#safety
250+ /// [valid]: crate:: ptr#safety
252251 /// [pointer metadata]: crate::ptr::metadata()
253252 ///
254253 /// # Panics
@@ -272,83 +271,20 @@ pub unsafe trait CloneToUninit {
272271
273272#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
274273unsafe 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 {
292274 #[ inline]
293275 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 { <T as self :: uninit:: CopySpec >:: clone_one ( self , dst) }
299278 }
300279}
301280
302281#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
303282unsafe 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 < T > ] ) } ;
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 ] {
336283 #[ inline]
337284 #[ cfg_attr( debug_assertions, track_caller) ]
338285 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 { <T as self :: uninit:: CopySpec >:: clone_slice ( self , dst) }
352288 }
353289}
354290
@@ -374,53 +310,6 @@ unsafe impl CloneToUninit for crate::ffi::CStr {
374310 }
375311}
376312
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 < T > ] ,
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 < T > ] ) -> 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-
424313/// Implementations of `Clone` for primitive types.
425314///
426315/// Implementations that cannot be described in Rust
0 commit comments