@@ -439,6 +439,16 @@ pub struct AssertParamIsCopy<T: Copy + PointeeSized> {
439439/// // All fields of the struct have been initialized; therefore, the struct is initialized,
440440/// // and we have satisfied our `unsafe impl CloneToUninit` obligations.
441441/// }
442+ ///
443+ /// unsafe fn clone_to_init(&self, dest: *mut u8) {
444+ /// // SAFETY: The caller must provide a `dest` such that these field offsets are valid
445+ /// // to write to.
446+ /// unsafe {
447+ /// let offset_of_contents = (&raw const self.contents).byte_offset_from_unsigned(self);
448+ /// self.contents.clone_to_init(dest.add(offset_of_contents));
449+ /// self.label.clone_to_init(dest.add(offset_of!(Self, label)));
450+ /// }
451+ /// }
442452/// }
443453///
444454/// fn main() {
@@ -509,6 +519,15 @@ pub unsafe trait CloneToUninit {
509519 /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo`
510520 /// cloned should be dropped.)
511521 unsafe fn clone_to_uninit ( & self , dest : * mut u8 ) ;
522+
523+ /// Clones `self` to `dest`
524+ ///
525+ /// This is similar to `Clone::clone_from`, but unsafe and dyn-compatible.
526+ ///
527+ /// # Safety
528+ ///
529+ /// `dest` must be a valid pointer to a valid value of the same concrete type than `self`.
530+ unsafe fn clone_to_init ( & self , dest : * mut u8 ) ;
512531}
513532
514533#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
@@ -518,6 +537,13 @@ unsafe impl<T: Clone> CloneToUninit for T {
518537 // SAFETY: we're calling a specialization with the same contract
519538 unsafe { <T as self :: uninit:: CopySpec >:: clone_one ( self , dest. cast :: < T > ( ) ) }
520539 }
540+
541+ #[ inline]
542+ unsafe fn clone_to_init ( & self , dest : * mut u8 ) {
543+ // SAFETY: by contract, `dest` is a valid pointer to `T`
544+ let dest = unsafe { dest. cast :: < T > ( ) . as_mut_unchecked ( ) } ;
545+ dest. clone_from ( self ) ;
546+ }
521547}
522548
523549#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
@@ -529,6 +555,15 @@ unsafe impl<T: Clone> CloneToUninit for [T] {
529555 // SAFETY: we're calling a specialization with the same contract
530556 unsafe { <T as self :: uninit:: CopySpec >:: clone_slice ( self , dest) }
531557 }
558+
559+ #[ inline]
560+ #[ cfg_attr( debug_assertions, track_caller) ]
561+ unsafe fn clone_to_init ( & self , dest : * mut u8 ) {
562+ // SAFETY: by contract, `dest` is a valid pointer to a `[T]` with the
563+ // same length as `self`
564+ let dest = unsafe { dest. with_metadata_of ( self ) . as_mut_unchecked ( ) } ;
565+ dest. clone_from_slice ( self ) ;
566+ }
532567}
533568
534569#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
@@ -539,18 +574,33 @@ unsafe impl CloneToUninit for str {
539574 // SAFETY: str is just a [u8] with UTF-8 invariant
540575 unsafe { self . as_bytes ( ) . clone_to_uninit ( dest) }
541576 }
577+
578+ #[ inline]
579+ #[ cfg_attr( debug_assertions, track_caller) ]
580+ unsafe fn clone_to_init ( & self , dest : * mut u8 ) {
581+ // SAFETY: str is just a [u8] with UTF-8 invariant
582+ unsafe { self . as_bytes ( ) . clone_to_init ( dest) }
583+ }
542584}
543585
544586#[ unstable( feature = "clone_to_uninit" , issue = "126799" ) ]
545587unsafe impl CloneToUninit for crate :: ffi:: CStr {
546588 #[ cfg_attr( debug_assertions, track_caller) ]
547589 unsafe fn clone_to_uninit ( & self , dest : * mut u8 ) {
548- // SAFETY: For now, CStr is just a #[repr(trasnsparent )] [c_char] with some invariants.
590+ // SAFETY: For now, CStr is just a #[repr(transparent )] [c_char] with some invariants.
549591 // And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul).
550592 // The pointer metadata properly preserves the length (so NUL is also copied).
551593 // See: `cstr_metadata_is_length_with_nul` in tests.
552594 unsafe { self . to_bytes_with_nul ( ) . clone_to_uninit ( dest) }
553595 }
596+
597+ unsafe fn clone_to_init ( & self , dest : * mut u8 ) {
598+ // SAFETY: For now, CStr is just a #[repr(transparent)] [c_char] with some invariants.
599+ // And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul).
600+ // The pointer metadata properly preserves the length (so NUL is also copied).
601+ // See: `cstr_metadata_is_length_with_nul` in tests.
602+ unsafe { self . to_bytes_with_nul ( ) . clone_to_init ( dest) }
603+ }
554604}
555605
556606#[ unstable( feature = "bstr" , issue = "134915" ) ]
@@ -561,6 +611,12 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
561611 // SAFETY: ByteStr is a `#[repr(transparent)]` wrapper around `[u8]`
562612 unsafe { self . as_bytes ( ) . clone_to_uninit ( dst) }
563613 }
614+
615+ #[ inline]
616+ unsafe fn clone_to_init ( & self , dst : * mut u8 ) {
617+ // SAFETY: ByteStr is a `#[repr(transparent)]` wrapper around `[u8]`
618+ unsafe { self . as_bytes ( ) . clone_to_uninit ( dst) }
619+ }
564620}
565621
566622/// Implementations of `Clone` for primitive types.
0 commit comments