@@ -336,19 +336,29 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
336
336
/// // The offset of `self.contents` is dynamic because it depends on the alignment of T
337
337
/// // which can be dynamic (if `T = dyn SomeTrait`). Therefore, we have to obtain it
338
338
/// // 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
+ /// }
352
362
///
353
363
/// // All fields of the struct have been initialized, therefore the struct is initialized,
354
364
/// // and we have satisfied our `unsafe impl CloneToUninit` obligations.
@@ -370,6 +380,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
370
380
///
371
381
/// assert_eq!(first.contents, [1, 2, 3, 4]);
372
382
/// assert_eq!(second.contents, [10, 20, 30, 40]);
383
+ /// assert_eq!(second.flag, true);
373
384
/// }
374
385
/// ```
375
386
///
@@ -414,9 +425,8 @@ pub unsafe trait CloneToUninit {
414
425
/// read or dropped, because even if it was previously valid, it may have been partially
415
426
/// overwritten.
416
427
///
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).
420
430
///
421
431
/// Implementors should avoid leaking values by, upon unwinding, dropping all component values
422
432
/// that might have already been created. (For example, if a `[Foo]` of length 3 is being
0 commit comments