zerocopy

Macro try_transmute_mut

Source
macro_rules! try_transmute_mut {
    ($e:expr) => { ... };
}
Expand description

Conditionally transmutes a mutable reference of one type to a mutable reference of another type of the same size and compatible alignment.

This macro behaves like an invocation of this function:

fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
where
    Src: IntoBytes,
    Dst: TryFromBytes,
    size_of::<Src>() == size_of::<Dst>(),
    align_of::<Src>() >= align_of::<Dst>(),
{
    ...
}

However, unlike a function, this macro can only be invoked when the types of Src and Dst are completely concrete. The types Src and Dst are inferred from the calling context; they cannot be explicitly specified in the macro invocation.

§Examples

// 0u8 → bool = false
let src = &mut 0u8;
assert_eq!(try_transmute_mut!(src), Ok(&mut false));

// 1u8 → bool = true
let src = &mut 1u8;
 assert_eq!(try_transmute_mut!(src), Ok(&mut true));

// 2u8 → bool = error
let src = &mut 2u8;
assert!(matches!(
    try_transmute_mut!(src),
    Result::<&mut bool, _>::Err(ValidityError { .. })
));

§Alignment increase error message

Because of limitations on macros, the error message generated when try_transmute_ref! is used to transmute from a type of lower alignment to a type of higher alignment is somewhat confusing. For example, the following code:

let src = &mut [0u8; 2];
let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);

…generates the following error:

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
 --> example.rs:2:51
  |
2 |     let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
  |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: source type: `AlignOf<[u8; 2]>` (8 bits)
  = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
  = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

This is saying that max(align_of::<T>(), align_of::<U>()) != align_of::<T>(), which is equivalent to align_of::<T>() < align_of::<U>().