@@ -327,7 +327,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
327327///
328328/// #[derive(PartialEq)]
329329/// struct MyDst<T: ?Sized> {
330- /// flag: bool ,
330+ /// label: String ,
331331/// contents: T,
332332/// }
333333///
@@ -343,32 +343,34 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
343343/// (&raw const self.contents).byte_offset_from_unsigned(self)
344344/// };
345345///
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
357353/// // to write to.
358354/// unsafe {
359- /// self.flag.clone_to_uninit( dest.add(offset_of!(Self, flag)));
355+ /// // Clone the unsized field directly from ` self` to ` dest`.
360356/// self.contents.clone_to_uninit(dest.add(offset_of_contents));
361- /// }
362357///
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,
364366/// // and we have satisfied our `unsafe impl CloneToUninit` obligations.
365367/// }
366368/// }
367369///
368370/// fn main() {
369371/// // Construct MyDst<[u8; 4]>, then coerce to MyDst<[u8]>.
370372/// let first: Rc<MyDst<[u8]>> = Rc::new(MyDst {
371- /// flag: true ,
373+ /// label: String::from("hello") ,
372374/// contents: [1, 2, 3, 4],
373375/// });
374376///
@@ -380,7 +382,7 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
380382///
381383/// assert_eq!(first.contents, [1, 2, 3, 4]);
382384/// assert_eq!(second.contents, [10, 20, 30, 40]);
383- /// assert_eq!(second.flag, true );
385+ /// assert_eq!(second.label, "hello" );
384386/// }
385387/// ```
386388///
0 commit comments