Repository: bevyengine/bevy
File: crates/bevy_ptr/src/lib.rs (Rust)

Code before:
        // Specify the type to make sure we don't `mem::forget` a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
        let _ = || {
            let value = &mut *ptr;
            // If a field is mentioned twice, this will cause mutable aliasing and fail to compile.
            let _ = ($(&mut value.$field_index),*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - We call `mem::forget` on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation
        $(let $field_alias = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
        core::mem::forget(ptr);
    };
    ($ptr:ident: MaybeUninit => {$($field_name:tt),* $(,)?}) => {
        $crate::deconstruct_moving_ptr!($ptr: MaybeUninit => ($($field_name => $field_name,)*))
    };
    ($ptr:ident: MaybeUninit => ($($field_index:tt => $field_alias:ident),* $(,)?)) => {
        // Specify the type to make sure we don't `mem::forget` a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
        let _ = || {
            // SAFETY: This closure is never called
            let value = unsafe { ptr.assume_init_mut() };
            // If a field is mentioned twice, this will cause mutable aliasing and fail to compile.
            let _ = ($(&mut value.$field_index),*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - We call `mem::forget` on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation
        $(let $field_alias = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
        core::mem::forget(ptr);
    };
}


Review comment (suggestion):
I'd write these into `$field_alias` and call `core::hint::black_box` on them instead to ensure that the compiler doesn't try to get smart and shorten their lifetimes.

Code after:
///
/// assert_eq!(target_a.0, 11);
/// assert_eq!(target_b.0, 22);
/// assert_eq!(target_c.0, 33);
/// ```
///
/// ## `MaybeUninit`
///
/// ```
/// use core::mem::{offset_of, MaybeUninit};
/// use bevy_ptr::{MovingPtr, move_as_ptr};
/// # use bevy_ptr::Unaligned;
/// # struct FieldAType(usize);
/// # struct FieldBType(usize);
/// # struct FieldCType(usize);
///
/// # pub struct Parent {
/// #  pub field_a: FieldAType,
/// #  pub field_b: FieldBType,
/// #  pub field_c: FieldCType,
/// # }
///
/// let parent = MaybeUninit::new(Parent {
///   field_a: FieldAType(11),
///   field_b: FieldBType(22),
///   field_c: FieldCType(33),
/// });
///
/// let mut target_a = MaybeUninit::new(FieldAType(101));
/// let mut target_b = MaybeUninit::new(FieldBType(102));
/// let mut target_c = MaybeUninit::new(FieldCType(103));
///
/// // Converts `parent` into a `MovingPtr`
/// move_as_ptr!(parent);
///
/// // The field names must match the name used in the type definition.
/// // Each one will be a `MovingPtr` of the field's type.
/// bevy_ptr::deconstruct_moving_ptr!({
///   let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;
/// });
///
/// field_a.assign_to(&mut target_a);
/// field_b.assign_to(&mut target_b);
/// field_c.assign_to(&mut target_c);
///
/// unsafe {
///   assert_eq!(target_a.assume_init().0, 11);
///   assert_eq!(target_b.assume_init().0, 22);
///   assert_eq!(target_c.assume_init().0, 33);
/// }
/// ```