Skip to content

Commit c286994

Browse files
authored
must_cast: fix test failures and fmt. (Lokathor#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.
1 parent 8f130f2 commit c286994

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

src/must.rs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,30 @@ use core::mem::{align_of, size_of};
88

99
struct Cast<A, B>((A, B));
1010
impl<A, B> Cast<A, B> {
11-
const ASSERT_ALIGN_GREATER_THAN_EQUAL : () = assert!(align_of::<A>() >= align_of::<B>());
12-
const ASSERT_SIZE_EQUAL : () = assert!(size_of::<A>() == size_of::<B>());
13-
const ASSERT_SIZE_MULTIPLE_OF : () = assert!((size_of::<A>() == 0) == (size_of::<B>() == 0) && (size_of::<A>() % size_of::<B>() == 0));
11+
const ASSERT_ALIGN_GREATER_THAN_EQUAL: () =
12+
assert!(align_of::<A>() >= align_of::<B>());
13+
const ASSERT_SIZE_EQUAL: () = assert!(size_of::<A>() == size_of::<B>());
14+
const ASSERT_SIZE_MULTIPLE_OF: () = assert!(
15+
(size_of::<A>() == 0) == (size_of::<B>() == 0)
16+
&& (size_of::<A>() % size_of::<B>() == 0)
17+
);
18+
}
19+
20+
// Workaround for https://github.com/rust-lang/miri/issues/2423.
21+
// Miri currently doesn't see post-monomorphization errors until runtime,
22+
// so `compile_fail` tests relying on post-monomorphization errors don't
23+
// actually fail. Instead use `should_panic` under miri as a workaround.
24+
#[cfg(miri)]
25+
macro_rules! post_mono_compile_fail_doctest {
26+
() => {
27+
"```should_panic"
28+
};
29+
}
30+
#[cfg(not(miri))]
31+
macro_rules! post_mono_compile_fail_doctest {
32+
() => {
33+
"```compile_fail,E0080"
34+
};
1435
}
1536

1637
/// Cast `A` into `B` if infalliable, or fail to compile.
@@ -27,9 +48,9 @@ impl<A, B> Cast<A, B> {
2748
/// ## Examples
2849
/// ```
2950
/// // compiles:
30-
/// let bytes : [u8; 2] = bytemuck::must_cast(12_u16);
51+
/// let bytes: [u8; 2] = bytemuck::must_cast(12_u16);
3152
/// ```
32-
/// ```compile_fail,E0080
53+
#[doc = post_mono_compile_fail_doctest!()]
3354
/// // fails to compile (size mismatch):
3455
/// let bytes : [u8; 3] = bytemuck::must_cast(12_u16);
3556
/// ```
@@ -49,13 +70,13 @@ pub fn must_cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
4970
/// ## Examples
5071
/// ```
5172
/// // compiles:
52-
/// let bytes : &[u8; 2] = bytemuck::must_cast_ref(&12_u16);
73+
/// let bytes: &[u8; 2] = bytemuck::must_cast_ref(&12_u16);
5374
/// ```
54-
/// ```compile_fail,E0080
75+
#[doc = post_mono_compile_fail_doctest!()]
5576
/// // fails to compile (size mismatch):
5677
/// let bytes : &[u8; 3] = bytemuck::must_cast_ref(&12_u16);
5778
/// ```
58-
/// ```compile_fail,E0080
79+
#[doc = post_mono_compile_fail_doctest!()]
5980
/// // fails to compile (alignment requirements increased):
6081
/// let bytes : &u16 = bytemuck::must_cast_ref(&[1u8, 2u8]);
6182
/// ```
@@ -74,15 +95,14 @@ pub fn must_cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
7495
/// ```
7596
/// let mut i = 12_u16;
7697
/// // compiles:
77-
/// let bytes : &mut [u8; 2] = bytemuck::must_cast_mut(&mut i);
98+
/// let bytes: &mut [u8; 2] = bytemuck::must_cast_mut(&mut i);
7899
/// ```
79-
/// ```compile_fail,E0080
80-
/// # let mut bytes : [u8; 2] = [1, 2];
81-
/// # let bytes = &mut bytes[..];
100+
#[doc = post_mono_compile_fail_doctest!()]
101+
/// # let mut bytes: &mut [u8; 2] = &mut [1, 2];
82102
/// // fails to compile (alignment requirements increased):
83103
/// let i : &mut u16 = bytemuck::must_cast_mut(bytes);
84104
/// ```
85-
/// ```compile_fail,E0080
105+
#[doc = post_mono_compile_fail_doctest!()]
86106
/// # let mut i = 12_u16;
87107
/// // fails to compile (size mismatch):
88108
/// let bytes : &mut [u8; 3] = bytemuck::must_cast_mut(&mut i);
@@ -99,31 +119,32 @@ pub fn must_cast_mut<
99119
unsafe { &mut *(a as *mut A as *mut B) }
100120
}
101121

102-
/// Convert `&[A]` into `&[B]` (possibly with a change in length) if infalliable, or fail to compile.
122+
/// Convert `&[A]` into `&[B]` (possibly with a change in length) if
123+
/// infalliable, or fail to compile.
103124
///
104125
/// * `input.as_ptr() as usize == output.as_ptr() as usize`
105126
/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
106127
///
107128
/// ## Failure
108129
///
109130
/// * If the target type has a greater alignment requirement.
110-
/// * If the target element type doesn't evenly fit into the the current element type
111-
/// (eg: 3 `u16` values is 1.5 `u32` values, so that's a failure).
131+
/// * If the target element type doesn't evenly fit into the the current element
132+
/// type (eg: 3 `u16` values is 1.5 `u32` values, so that's a failure).
112133
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
113134
/// and a non-ZST.
114135
///
115136
/// ## Examples
116137
/// ```
117-
/// let indicies : &[u16] = &[1, 2, 3];
138+
/// let indicies: &[u16] = &[1, 2, 3];
118139
/// // compiles:
119-
/// let bytes : &[u8] = bytemuck::must_cast_slice(indicies);
140+
/// let bytes: &[u8] = bytemuck::must_cast_slice(indicies);
120141
/// ```
121-
/// ```compile_fail,E0080
122-
/// # let bytes : &[u8] = [1, 0, 2, 0, 3, 0];
142+
#[doc = post_mono_compile_fail_doctest!()]
143+
/// # let bytes : &[u8] = &[1, 0, 2, 0, 3, 0];
123144
/// // fails to compile (bytes.len() might not be a multiple of 2):
124145
/// let byte_pairs : &[[u8; 2]] = bytemuck::must_cast_slice(bytes);
125146
/// ```
126-
/// ```compile_fail,E0080
147+
#[doc = post_mono_compile_fail_doctest!()]
127148
/// # let byte_pairs : &[[u8; 2]] = &[[1, 0], [2, 0], [3, 0]];
128149
/// // fails to compile (alignment requirements increased):
129150
/// 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] {
140161
unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, new_len) }
141162
}
142163

143-
/// Convert `&mut [A]` into `&mut [B]` (possibly with a change in length) if infalliable, or fail to compile.
164+
/// Convert `&mut [A]` into `&mut [B]` (possibly with a change in length) if
165+
/// infalliable, or fail to compile.
144166
///
145167
/// As [`must_cast_slice`], but `&mut`.
146168
///
147169
/// ## Examples
148170
/// ```
149171
/// let mut indicies = [1, 2, 3];
150-
/// let indicies : &mut [u16] = &mut indicies;
172+
/// let indicies: &mut [u16] = &mut indicies;
151173
/// // compiles:
152-
/// let bytes : &mut [u8] = bytemuck::must_cast_slice_mut(indicies);
174+
/// let bytes: &mut [u8] = bytemuck::must_cast_slice_mut(indicies);
153175
/// ```
154-
/// ```compile_fail,E0080
176+
#[doc = post_mono_compile_fail_doctest!()]
155177
/// # let mut bytes = [1, 0, 2, 0, 3, 0];
156178
/// # let bytes : &mut [u8] = &mut bytes[..];
157179
/// // fails to compile (bytes.len() might not be a multiple of 2):
158180
/// let byte_pairs : &mut [[u8; 2]] = bytemuck::must_cast_slice_mut(bytes);
159181
/// ```
160-
/// ```compile_fail,E0080
182+
#[doc = post_mono_compile_fail_doctest!()]
161183
/// # let mut byte_pairs = [[1, 0], [2, 0], [3, 0]];
162184
/// # let byte_pairs : &mut [[u8; 2]] = &mut byte_pairs[..];
163185
/// // fails to compile (alignment requirements increased):

0 commit comments

Comments
 (0)