@@ -327,7 +327,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
327
327
///
328
328
/// #[derive(PartialEq)]
329
329
/// struct MyDst<T: ?Sized> {
330
- /// flag: bool ,
330
+ /// label: String ,
331
331
/// contents: T,
332
332
/// }
333
333
///
@@ -343,32 +343,34 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
343
343
/// (&raw const self.contents).byte_offset_from_unsigned(self)
344
344
/// };
345
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
346
+ /// // Clone the *sized* fields of `self` (just one, in this example).
347
+ /// // (By cloning this first and storing it temporarily in a local variable, we avoid
348
+ /// // leaking it in case of any panic, using the ordinary automatic cleanup of local
349
+ /// // variables. Such a leak would be sound, but undesirable.)
350
+ /// let label = self.label.clone();
351
+ ///
352
+ /// // SAFETY: The caller must provide a `dest` such that these field offsets are valid
357
353
/// // to write to.
358
354
/// unsafe {
359
- /// self.flag.clone_to_uninit( dest.add(offset_of!(Self, flag)));
355
+ /// // Clone the unsized field directly from ` self` to ` dest`.
360
356
/// self.contents.clone_to_uninit(dest.add(offset_of_contents));
361
- /// }
362
357
///
363
- /// // All fields of the struct have been initialized, therefore the struct is initialized,
358
+ /// // Now write all the sized fields.
359
+ /// //
360
+ /// // Note that we only do this once all of the clone() and clone_to_uninit() calls
361
+ /// // have completed, and therefore we know that there are no more possible panics;
362
+ /// // this ensures no memory leaks in case of panic.
363
+ /// dest.add(offset_of!(Self, label)).cast::<String>().write(label);
364
+ /// }
365
+ /// // All fields of the struct have been initialized; therefore, the struct is initialized,
364
366
/// // and we have satisfied our `unsafe impl CloneToUninit` obligations.
365
367
/// }
366
368
/// }
367
369
///
368
370
/// fn main() {
369
371
/// // Construct MyDst<[u8; 4]>, then coerce to MyDst<[u8]>.
370
372
/// let first: Rc<MyDst<[u8]>> = Rc::new(MyDst {
371
- /// flag: true ,
373
+ /// label: String::from("hello") ,
372
374
/// contents: [1, 2, 3, 4],
373
375
/// });
374
376
///
@@ -380,7 +382,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
380
382
///
381
383
/// assert_eq!(first.contents, [1, 2, 3, 4]);
382
384
/// assert_eq!(second.contents, [10, 20, 30, 40]);
383
- /// assert_eq!(second.flag, true );
385
+ /// assert_eq!(second.label, "hello" );
384
386
/// }
385
387
/// ```
386
388
///
0 commit comments