must_cast: fix test failures and fmt. (#194)

* cargo fmt src/must.rs

* Fix must.rs test failures.

* Under miri, use should_panic instead of compile_fail for must_cast doctests.

* Add description for workaround.
This commit is contained in:
zachs18 2023-06-15 10:54:23 -05:00 committed by GitHub
parent 8f130f2b79
commit c286994891
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,9 +8,30 @@ use core::mem::{align_of, size_of};
struct Cast<A, B>((A, B));
impl<A, B> Cast<A, B> {
const ASSERT_ALIGN_GREATER_THAN_EQUAL : () = assert!(align_of::<A>() >= align_of::<B>());
const ASSERT_SIZE_EQUAL : () = assert!(size_of::<A>() == size_of::<B>());
const ASSERT_SIZE_MULTIPLE_OF : () = assert!((size_of::<A>() == 0) == (size_of::<B>() == 0) && (size_of::<A>() % size_of::<B>() == 0));
const ASSERT_ALIGN_GREATER_THAN_EQUAL: () =
assert!(align_of::<A>() >= align_of::<B>());
const ASSERT_SIZE_EQUAL: () = assert!(size_of::<A>() == size_of::<B>());
const ASSERT_SIZE_MULTIPLE_OF: () = assert!(
(size_of::<A>() == 0) == (size_of::<B>() == 0)
&& (size_of::<A>() % size_of::<B>() == 0)
);
}
// Workaround for https://github.com/rust-lang/miri/issues/2423.
// Miri currently doesn't see post-monomorphization errors until runtime,
// so `compile_fail` tests relying on post-monomorphization errors don't
// actually fail. Instead use `should_panic` under miri as a workaround.
#[cfg(miri)]
macro_rules! post_mono_compile_fail_doctest {
() => {
"```should_panic"
};
}
#[cfg(not(miri))]
macro_rules! post_mono_compile_fail_doctest {
() => {
"```compile_fail,E0080"
};
}
/// Cast `A` into `B` if infalliable, or fail to compile.
@ -27,9 +48,9 @@ impl<A, B> Cast<A, B> {
/// ## Examples
/// ```
/// // compiles:
/// let bytes : [u8; 2] = bytemuck::must_cast(12_u16);
/// let bytes: [u8; 2] = bytemuck::must_cast(12_u16);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// // fails to compile (size mismatch):
/// let bytes : [u8; 3] = bytemuck::must_cast(12_u16);
/// ```
@ -49,13 +70,13 @@ pub fn must_cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
/// ## Examples
/// ```
/// // compiles:
/// let bytes : &[u8; 2] = bytemuck::must_cast_ref(&12_u16);
/// let bytes: &[u8; 2] = bytemuck::must_cast_ref(&12_u16);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// // fails to compile (size mismatch):
/// let bytes : &[u8; 3] = bytemuck::must_cast_ref(&12_u16);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// // fails to compile (alignment requirements increased):
/// let bytes : &u16 = bytemuck::must_cast_ref(&[1u8, 2u8]);
/// ```
@ -74,15 +95,14 @@ pub fn must_cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
/// ```
/// let mut i = 12_u16;
/// // compiles:
/// let bytes : &mut [u8; 2] = bytemuck::must_cast_mut(&mut i);
/// let bytes: &mut [u8; 2] = bytemuck::must_cast_mut(&mut i);
/// ```
/// ```compile_fail,E0080
/// # let mut bytes : [u8; 2] = [1, 2];
/// # let bytes = &mut bytes[..];
#[doc = post_mono_compile_fail_doctest!()]
/// # let mut bytes: &mut [u8; 2] = &mut [1, 2];
/// // fails to compile (alignment requirements increased):
/// let i : &mut u16 = bytemuck::must_cast_mut(bytes);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// # let mut i = 12_u16;
/// // fails to compile (size mismatch):
/// let bytes : &mut [u8; 3] = bytemuck::must_cast_mut(&mut i);
@ -99,7 +119,8 @@ pub fn must_cast_mut<
unsafe { &mut *(a as *mut A as *mut B) }
}
/// Convert `&[A]` into `&[B]` (possibly with a change in length) if infalliable, or fail to compile.
/// Convert `&[A]` into `&[B]` (possibly with a change in length) if
/// infalliable, or fail to compile.
///
/// * `input.as_ptr() as usize == output.as_ptr() as usize`
/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
@ -107,23 +128,23 @@ pub fn must_cast_mut<
/// ## Failure
///
/// * If the target type has a greater alignment requirement.
/// * If the target element type doesn't evenly fit into the the current element type
/// (eg: 3 `u16` values is 1.5 `u32` values, so that's a failure).
/// * If the target element type doesn't evenly fit into the the current element
/// type (eg: 3 `u16` values is 1.5 `u32` values, so that's a failure).
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
/// and a non-ZST.
///
/// ## Examples
/// ```
/// let indicies : &[u16] = &[1, 2, 3];
/// let indicies: &[u16] = &[1, 2, 3];
/// // compiles:
/// let bytes : &[u8] = bytemuck::must_cast_slice(indicies);
/// let bytes: &[u8] = bytemuck::must_cast_slice(indicies);
/// ```
/// ```compile_fail,E0080
/// # let bytes : &[u8] = [1, 0, 2, 0, 3, 0];
#[doc = post_mono_compile_fail_doctest!()]
/// # let bytes : &[u8] = &[1, 0, 2, 0, 3, 0];
/// // fails to compile (bytes.len() might not be a multiple of 2):
/// let byte_pairs : &[[u8; 2]] = bytemuck::must_cast_slice(bytes);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// # let byte_pairs : &[[u8; 2]] = &[[1, 0], [2, 0], [3, 0]];
/// // fails to compile (alignment requirements increased):
/// let indicies : &[u16] = bytemuck::must_cast_slice(byte_pairs);
@ -140,24 +161,25 @@ pub fn must_cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, new_len) }
}
/// Convert `&mut [A]` into `&mut [B]` (possibly with a change in length) if infalliable, or fail to compile.
/// Convert `&mut [A]` into `&mut [B]` (possibly with a change in length) if
/// infalliable, or fail to compile.
///
/// As [`must_cast_slice`], but `&mut`.
///
/// ## Examples
/// ```
/// let mut indicies = [1, 2, 3];
/// let indicies : &mut [u16] = &mut indicies;
/// let indicies: &mut [u16] = &mut indicies;
/// // compiles:
/// let bytes : &mut [u8] = bytemuck::must_cast_slice_mut(indicies);
/// let bytes: &mut [u8] = bytemuck::must_cast_slice_mut(indicies);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// # let mut bytes = [1, 0, 2, 0, 3, 0];
/// # let bytes : &mut [u8] = &mut bytes[..];
/// // fails to compile (bytes.len() might not be a multiple of 2):
/// let byte_pairs : &mut [[u8; 2]] = bytemuck::must_cast_slice_mut(bytes);
/// ```
/// ```compile_fail,E0080
#[doc = post_mono_compile_fail_doctest!()]
/// # let mut byte_pairs = [[1, 0], [2, 0], [3, 0]];
/// # let byte_pairs : &mut [[u8; 2]] = &mut byte_pairs[..];
/// // fails to compile (alignment requirements increased):