@@ -336,19 +336,29 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
336336/// // The offset of `self.contents` is dynamic because it depends on the alignment of T
337337/// // which can be dynamic (if `T = dyn SomeTrait`). Therefore, we have to obtain it
338338/// // dynamically by examining `self`, rather than using `offset_of!`.
339- /// let offset_of_contents =
340- /// (&raw const self.contents).byte_offset_from_unsigned(&raw const *self);
341- ///
342- /// // Since `flag` implements `Copy`, we can just copy it.
343- /// // We use `pointer::write()` instead of assignment because the destination must be
344- /// // assumed to be uninitialized, whereas an assignment assumes it is initialized.
345- /// dest.add(offset_of!(Self, flag)).cast::<bool>().write(self.flag);
346- ///
347- /// // Note: if `flag` owned any resources (i.e. had a `Drop` implementation), then we
348- /// // must prepare to drop it in case `self.contents.clone_to_uninit()` panics.
349- /// // In this simple case, where we have exactly one field for which `mem::needs_drop()`
350- /// // might be true (`contents`), we don’t need to care about cleanup or ordering.
351- /// self.contents.clone_to_uninit(dest.add(offset_of_contents));
339+ /// //
340+ /// // SAFETY: `self` by definition points somewhere before `&self.contents` in the same
341+ /// // allocation.
342+ /// let offset_of_contents = unsafe {
343+ /// (&raw const self.contents).byte_offset_from_unsigned(self)
344+ /// };
345+ ///
346+ /// // Clone each field of `self` into `dest`.
347+ /// //
348+ /// // Since `flag` is `Sized`, we could also clone it as
349+ /// // dest.add(offset_of!(Self, flag)).cast::<bool>().write(self.flag.clone());
350+ /// // Since it is `Copy` (and therefore does not have a destructor), we could even write
351+ /// // *dest.add(offset_of!(Self, flag)) = self.flag;
352+ /// // but that must not be used for types with destructors, since it would read the place
353+ /// // in order to drop the old value. We have chosen to do neither of those, to demonstrate
354+ /// // the most general pattern.
355+ /// //
356+ /// // SAFETY: The caller must provide a `dest` such that these offsets are valid
357+ /// // to write to.
358+ /// unsafe {
359+ /// self.flag.clone_to_uninit(dest.add(offset_of!(Self, flag)));
360+ /// self.contents.clone_to_uninit(dest.add(offset_of_contents));
361+ /// }
352362///
353363/// // All fields of the struct have been initialized, therefore the struct is initialized,
354364/// // and we have satisfied our `unsafe impl CloneToUninit` obligations.
@@ -370,6 +380,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
370380///
371381/// assert_eq!(first.contents, [1, 2, 3, 4]);
372382/// assert_eq!(second.contents, [10, 20, 30, 40]);
383+ /// assert_eq!(second.flag, true);
373384/// }
374385/// ```
375386///
@@ -414,9 +425,8 @@ pub unsafe trait CloneToUninit {
414425 /// read or dropped, because even if it was previously valid, it may have been partially
415426 /// overwritten.
416427 ///
417- /// The caller may also need to take care to deallocate the allocation pointed to by `dest`,
418- /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure
419- /// soundness in the presence of unwinding.
428+ /// The caller may wish to to take care to deallocate the allocation pointed to by `dest`,
429+ /// if applicable, to avoid a memory leak (but this is not a requirement).
420430 ///
421431 /// Implementors should avoid leaking values by, upon unwinding, dropping all component values
422432 /// that might have already been created. (For example, if a `[Foo]` of length 3 is being
0 commit comments