1 // Copyright 2024 The Fuchsia Authors 2 // 3 // Licensed under the 2-Clause BSD License <LICENSE-BSD or 4 // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0 5 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 6 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 7 // This file may not be copied, modified, or distributed except according to 8 // those terms. 9 10 use core::{ 11 cell::{Cell, UnsafeCell}, 12 mem::MaybeUninit as CoreMaybeUninit, 13 ptr::NonNull, 14 }; 15 16 use super::*; 17 use crate::pointer::cast::{CastSizedExact, CastUnsized}; 18 19 // SAFETY: Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a 20 // zero-sized type to have a size of 0 and an alignment of 1." 21 // - `Immutable`: `()` self-evidently does not contain any `UnsafeCell`s. 22 // - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: There is only 23 // one possible sequence of 0 bytes, and `()` is inhabited. 24 // - `IntoBytes`: Since `()` has size 0, it contains no padding bytes. 25 // - `Unaligned`: `()` has alignment 1. 26 // 27 // [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#tuple-layout 28 #[allow(clippy::multiple_unsafe_ops_per_block)] 29 const _: () = unsafe { 30 unsafe_impl!((): Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 31 assert_unaligned!(()); 32 }; 33 34 // SAFETY: 35 // - `Immutable`: These types self-evidently do not contain any `UnsafeCell`s. 36 // - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: all bit 37 // patterns are valid for numeric types [1] 38 // - `IntoBytes`: numeric types have no padding bytes [1] 39 // - `Unaligned` (`u8` and `i8` only): The reference [2] specifies the size of 40 // `u8` and `i8` as 1 byte. We also know that: 41 // - Alignment is >= 1 [3] 42 // - Size is an integer multiple of alignment [4] 43 // - The only value >= 1 for which 1 is an integer multiple is 1 Therefore, 44 // the only possible alignment for `u8` and `i8` is 1. 45 // 46 // [1] Per https://doc.rust-lang.org/1.81.0/reference/types/numeric.html#bit-validity: 47 // 48 // For every numeric type, `T`, the bit validity of `T` is equivalent to 49 // the bit validity of `[u8; size_of::<T>()]`. An uninitialized byte is 50 // not a valid `u8`. 51 // 52 // [2] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#primitive-data-layout 53 // 54 // [3] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: 55 // 56 // Alignment is measured in bytes, and must be at least 1. 57 // 58 // [4] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: 59 // 60 // The size of a value is always a multiple of its alignment. 61 // 62 // FIXME(#278): Once we've updated the trait docs to refer to `u8`s rather than 63 // bits or bytes, update this comment, especially the reference to [1]. 64 #[allow(clippy::multiple_unsafe_ops_per_block)] 65 const _: () = unsafe { 66 unsafe_impl!(u8: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 67 unsafe_impl!(i8: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 68 assert_unaligned!(u8, i8); 69 unsafe_impl!(u16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 70 unsafe_impl!(i16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 71 unsafe_impl!(u32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 72 unsafe_impl!(i32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 73 unsafe_impl!(u64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 74 unsafe_impl!(i64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 75 unsafe_impl!(u128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 76 unsafe_impl!(i128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 77 unsafe_impl!(usize: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 78 unsafe_impl!(isize: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 79 unsafe_impl!(f32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 80 unsafe_impl!(f64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 81 #[cfg(feature = "float-nightly")] 82 unsafe_impl!(#[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] f16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 83 #[cfg(feature = "float-nightly")] 84 unsafe_impl!(#[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] f128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); 85 }; 86 87 // SAFETY: 88 // - `Immutable`: `bool` self-evidently does not contain any `UnsafeCell`s. 89 // - `FromZeros`: Valid since "[t]he value false has the bit pattern 0x00" [1]. 90 // - `IntoBytes`: Since "the boolean type has a size and alignment of 1 each" 91 // and "The value false has the bit pattern 0x00 and the value true has the 92 // bit pattern 0x01" [1]. Thus, the only byte of the bool is always 93 // initialized. 94 // - `Unaligned`: Per the reference [1], "[a]n object with the boolean type has 95 // a size and alignment of 1 each." 96 // 97 // [1] https://doc.rust-lang.org/1.81.0/reference/types/boolean.html 98 #[allow(clippy::multiple_unsafe_ops_per_block)] 99 const _: () = unsafe { unsafe_impl!(bool: Immutable, FromZeros, IntoBytes, Unaligned) }; 100 assert_unaligned!(bool); 101 102 // SAFETY: The impl must only return `true` for its argument if the original 103 // `Maybe<bool>` refers to a valid `bool`. We only return true if the `u8` value 104 // is 0 or 1, and both of these are valid values for `bool` [1]. 105 // 106 // [1] Per https://doc.rust-lang.org/1.81.0/reference/types/boolean.html: 107 // 108 // The value false has the bit pattern 0x00 and the value true has the bit 109 // pattern 0x01. 110 const _: () = unsafe { 111 unsafe_impl!(=> TryFromBytes for bool; |byte| { 112 let byte = byte.transmute_with::<u8, invariant::Valid, CastSizedExact, BecauseImmutable>(); 113 *byte.unaligned_as_ref() < 2 114 }) 115 }; 116 117 // SAFETY: 118 // - `Immutable`: `char` self-evidently does not contain any `UnsafeCell`s. 119 // - `FromZeros`: Per reference [1], "[a] value of type char is a Unicode scalar 120 // value (i.e. a code point that is not a surrogate), represented as a 32-bit 121 // unsigned word in the 0x0000 to 0xD7FF or 0xE000 to 0x10FFFF range" which 122 // contains 0x0000. 123 // - `IntoBytes`: `char` is per reference [1] "represented as a 32-bit unsigned 124 // word" (`u32`) which is `IntoBytes`. Note that unlike `u32`, not all bit 125 // patterns are valid for `char`. 126 // 127 // [1] https://doc.rust-lang.org/1.81.0/reference/types/textual.html 128 #[allow(clippy::multiple_unsafe_ops_per_block)] 129 const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) }; 130 131 // SAFETY: The impl must only return `true` for its argument if the original 132 // `Maybe<char>` refers to a valid `char`. `char::from_u32` guarantees that it 133 // returns `None` if its input is not a valid `char` [1]. 134 // 135 // [1] Per https://doc.rust-lang.org/core/primitive.char.html#method.from_u32: 136 // 137 // `from_u32()` will return `None` if the input is not a valid value for a 138 // `char`. 139 const _: () = unsafe { 140 unsafe_impl!(=> TryFromBytes for char; |c| { 141 let c = c.transmute_with::<Unalign<u32>, invariant::Valid, CastSizedExact, BecauseImmutable>(); 142 let c = c.read().into_inner(); 143 char::from_u32(c).is_some() 144 }); 145 }; 146 147 // SAFETY: Per the Reference [1], `str` has the same layout as `[u8]`. 148 // - `Immutable`: `[u8]` does not contain any `UnsafeCell`s. 149 // - `FromZeros`, `IntoBytes`, `Unaligned`: `[u8]` is `FromZeros`, `IntoBytes`, 150 // and `Unaligned`. 151 // 152 // Note that we don't `assert_unaligned!(str)` because `assert_unaligned!` uses 153 // `align_of`, which only works for `Sized` types. 154 // 155 // FIXME(#429): Improve safety proof for `FromZeros` and `IntoBytes`; having the same 156 // layout as `[u8]` isn't sufficient. 157 // 158 // [1] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#str-layout: 159 // 160 // String slices are a UTF-8 representation of characters that have the same 161 // layout as slices of type `[u8]`. 162 #[allow(clippy::multiple_unsafe_ops_per_block)] 163 const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unaligned) }; 164 165 // SAFETY: The impl must only return `true` for its argument if the original 166 // `Maybe<str>` refers to a valid `str`. `str::from_utf8` guarantees that it 167 // returns `Err` if its input is not a valid `str` [1]. 168 // 169 // [1] Per https://doc.rust-lang.org/core/str/fn.from_utf8.html#errors: 170 // 171 // Returns `Err` if the slice is not UTF-8. 172 const _: () = unsafe { 173 unsafe_impl!(=> TryFromBytes for str; |c| { 174 let c = c.transmute_with::<[u8], invariant::Valid, CastUnsized, BecauseImmutable>(); 175 let c = c.unaligned_as_ref(); 176 core::str::from_utf8(c).is_ok() 177 }) 178 }; 179 180 macro_rules! unsafe_impl_try_from_bytes_for_nonzero { 181 ($($nonzero:ident[$prim:ty]),*) => { 182 $( 183 unsafe_impl!(=> TryFromBytes for $nonzero; |n| { 184 let n = n.transmute_with::<Unalign<$prim>, invariant::Valid, CastSizedExact, BecauseImmutable>(); 185 $nonzero::new(n.read().into_inner()).is_some() 186 }); 187 )* 188 } 189 } 190 191 // `NonZeroXxx` is `IntoBytes`, but not `FromZeros` or `FromBytes`. 192 // 193 // SAFETY: 194 // - `IntoBytes`: `NonZeroXxx` has the same layout as its associated primitive. 195 // Since it is the same size, this guarantees it has no padding - integers 196 // have no padding, and there's no room for padding if it can represent all 197 // of the same values except 0. 198 // - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that `Option<NonZeroU8>` 199 // and `Option<NonZeroI8>` both have size 1. [1] [2] This is worded in a way 200 // that makes it unclear whether it's meant as a guarantee, but given the 201 // purpose of those types, it's virtually unthinkable that that would ever 202 // change. `Option` cannot be smaller than its contained type, which implies 203 // that, and `NonZeroX8` are of size 1 or 0. `NonZeroX8` can represent 204 // multiple states, so they cannot be 0 bytes, which means that they must be 1 205 // byte. The only valid alignment for a 1-byte type is 1. 206 // 207 // FIXME(#429): 208 // - Add quotes from documentation. 209 // - Add safety comment for `Immutable`. How can we prove that `NonZeroXxx` 210 // doesn't contain any `UnsafeCell`s? It's obviously true, but it's not clear 211 // how we'd prove it short of adding text to the stdlib docs that says so 212 // explicitly, which likely wouldn't be accepted. 213 // 214 // [1] Per https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroU8.html: 215 // 216 // `NonZeroU8` is guaranteed to have the same layout and bit validity as `u8` with 217 // the exception that 0 is not a valid instance. 218 // 219 // [2] Per https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroI8.html: 220 // 221 // `NonZeroI8` is guaranteed to have the same layout and bit validity as `i8` with 222 // the exception that 0 is not a valid instance. 223 #[allow(clippy::multiple_unsafe_ops_per_block)] 224 const _: () = unsafe { 225 unsafe_impl!(NonZeroU8: Immutable, IntoBytes, Unaligned); 226 unsafe_impl!(NonZeroI8: Immutable, IntoBytes, Unaligned); 227 assert_unaligned!(NonZeroU8, NonZeroI8); 228 unsafe_impl!(NonZeroU16: Immutable, IntoBytes); 229 unsafe_impl!(NonZeroI16: Immutable, IntoBytes); 230 unsafe_impl!(NonZeroU32: Immutable, IntoBytes); 231 unsafe_impl!(NonZeroI32: Immutable, IntoBytes); 232 unsafe_impl!(NonZeroU64: Immutable, IntoBytes); 233 unsafe_impl!(NonZeroI64: Immutable, IntoBytes); 234 unsafe_impl!(NonZeroU128: Immutable, IntoBytes); 235 unsafe_impl!(NonZeroI128: Immutable, IntoBytes); 236 unsafe_impl!(NonZeroUsize: Immutable, IntoBytes); 237 unsafe_impl!(NonZeroIsize: Immutable, IntoBytes); 238 unsafe_impl_try_from_bytes_for_nonzero!( 239 NonZeroU8[u8], 240 NonZeroI8[i8], 241 NonZeroU16[u16], 242 NonZeroI16[i16], 243 NonZeroU32[u32], 244 NonZeroI32[i32], 245 NonZeroU64[u64], 246 NonZeroI64[i64], 247 NonZeroU128[u128], 248 NonZeroI128[i128], 249 NonZeroUsize[usize], 250 NonZeroIsize[isize] 251 ); 252 }; 253 254 // SAFETY: 255 // - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`, `IntoBytes`: 256 // The Rust compiler reuses `0` value to represent `None`, so 257 // `size_of::<Option<NonZeroXxx>>() == size_of::<xxx>()`; see `NonZeroXxx` 258 // documentation. 259 // - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that `Option<NonZeroU8>` 260 // and `Option<NonZeroI8>` both have size 1. [1] [2] This is worded in a way 261 // that makes it unclear whether it's meant as a guarantee, but given the 262 // purpose of those types, it's virtually unthinkable that that would ever 263 // change. The only valid alignment for a 1-byte type is 1. 264 // 265 // [1] Per https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroU8.html: 266 // 267 // `Option<NonZeroU8>` is guaranteed to be compatible with `u8`, including in FFI. 268 // 269 // Thanks to the null pointer optimization, `NonZeroU8` and `Option<NonZeroU8>` 270 // are guaranteed to have the same size and alignment: 271 // 272 // [2] Per https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroI8.html: 273 // 274 // `Option<NonZeroI8>` is guaranteed to be compatible with `i8`, including in FFI. 275 // 276 // Thanks to the null pointer optimization, `NonZeroI8` and `Option<NonZeroI8>` 277 // are guaranteed to have the same size and alignment: 278 #[allow(clippy::multiple_unsafe_ops_per_block)] 279 const _: () = unsafe { 280 unsafe_impl!(Option<NonZeroU8>: TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 281 unsafe_impl!(Option<NonZeroI8>: TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 282 assert_unaligned!(Option<NonZeroU8>, Option<NonZeroI8>); 283 unsafe_impl!(Option<NonZeroU16>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 284 unsafe_impl!(Option<NonZeroI16>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 285 unsafe_impl!(Option<NonZeroU32>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 286 unsafe_impl!(Option<NonZeroI32>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 287 unsafe_impl!(Option<NonZeroU64>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 288 unsafe_impl!(Option<NonZeroI64>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 289 unsafe_impl!(Option<NonZeroU128>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 290 unsafe_impl!(Option<NonZeroI128>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 291 unsafe_impl!(Option<NonZeroUsize>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 292 unsafe_impl!(Option<NonZeroIsize>: TryFromBytes, FromZeros, FromBytes, IntoBytes); 293 }; 294 295 // SAFETY: While it's not fully documented, the consensus is that `Box<T>` does 296 // not contain any `UnsafeCell`s for `T: Sized` [1]. This is not a complete 297 // proof, but we are accepting this as a known risk per #1358. 298 // 299 // [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/492 300 #[cfg(feature = "alloc")] 301 const _: () = unsafe { 302 unsafe_impl!( 303 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] 304 T: Sized => Immutable for Box<T> 305 ) 306 }; 307 308 // SAFETY: The following types can be transmuted from `[0u8; size_of::<T>()]`. [1] 309 // 310 // [1] Per https://doc.rust-lang.org/1.89.0/core/option/index.html#representation: 311 // 312 // Rust guarantees to optimize the following types `T` such that [`Option<T>`] 313 // has the same size and alignment as `T`. In some of these cases, Rust 314 // further guarantees that `transmute::<_, Option<T>>([0u8; size_of::<T>()])` 315 // is sound and produces `Option::<T>::None`. These cases are identified by 316 // the second column: 317 // 318 // | `T` | `transmute::<_, Option<T>>([0u8; size_of::<T>()])` sound? | 319 // |-----------------------------------|-----------------------------------------------------------| 320 // | [`Box<U>`] | when `U: Sized` | 321 // | `&U` | when `U: Sized` | 322 // | `&mut U` | when `U: Sized` | 323 // | [`ptr::NonNull<U>`] | when `U: Sized` | 324 // | `fn`, `extern "C" fn`[^extern_fn] | always | 325 // 326 // [^extern_fn]: this remains true for `unsafe` variants, any argument/return 327 // types, and any other ABI: `[unsafe] extern "abi" fn` (_e.g._, `extern 328 // "system" fn`) 329 #[allow(clippy::multiple_unsafe_ops_per_block)] 330 const _: () = unsafe { 331 #[cfg(feature = "alloc")] 332 unsafe_impl!( 333 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] 334 T => TryFromBytes for Option<Box<T>>; |c| pointer::is_zeroed(c) 335 ); 336 #[cfg(feature = "alloc")] 337 unsafe_impl!( 338 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] 339 T => FromZeros for Option<Box<T>> 340 ); 341 unsafe_impl!( 342 T => TryFromBytes for Option<&'_ T>; |c| pointer::is_zeroed(c) 343 ); 344 unsafe_impl!(T => FromZeros for Option<&'_ T>); 345 unsafe_impl!( 346 T => TryFromBytes for Option<&'_ mut T>; |c| pointer::is_zeroed(c) 347 ); 348 unsafe_impl!(T => FromZeros for Option<&'_ mut T>); 349 unsafe_impl!( 350 T => TryFromBytes for Option<NonNull<T>>; |c| pointer::is_zeroed(c) 351 ); 352 unsafe_impl!(T => FromZeros for Option<NonNull<T>>); 353 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_fn!(...)); 354 unsafe_impl_for_power_set!( 355 A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_fn!(...); 356 |c| pointer::is_zeroed(c) 357 ); 358 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_unsafe_fn!(...)); 359 unsafe_impl_for_power_set!( 360 A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_unsafe_fn!(...); 361 |c| pointer::is_zeroed(c) 362 ); 363 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_extern_c_fn!(...)); 364 unsafe_impl_for_power_set!( 365 A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_extern_c_fn!(...); 366 |c| pointer::is_zeroed(c) 367 ); 368 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_unsafe_extern_c_fn!(...)); 369 unsafe_impl_for_power_set!( 370 A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_unsafe_extern_c_fn!(...); 371 |c| pointer::is_zeroed(c) 372 ); 373 }; 374 375 // SAFETY: `[unsafe] [extern "C"] fn()` self-evidently do not contain 376 // `UnsafeCell`s. This is not a proof, but we are accepting this as a known risk 377 // per #1358. 378 #[allow(clippy::multiple_unsafe_ops_per_block)] 379 const _: () = unsafe { 380 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_fn!(...)); 381 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_unsafe_fn!(...)); 382 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_extern_c_fn!(...)); 383 unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_unsafe_extern_c_fn!(...)); 384 }; 385 386 #[cfg(all( 387 not(no_zerocopy_target_has_atomics_1_60_0), 388 any( 389 target_has_atomic = "8", 390 target_has_atomic = "16", 391 target_has_atomic = "32", 392 target_has_atomic = "64", 393 target_has_atomic = "ptr" 394 ) 395 ))] 396 #[cfg_attr(doc_cfg, doc(cfg(rust = "1.60.0")))] 397 mod atomics { 398 use super::*; 399 400 macro_rules! impl_traits_for_atomics { 401 ($($atomics:tt [$primitives:ty]),* $(,)?) => { 402 $( 403 impl_known_layout!($atomics); 404 impl_for_transmute_from!(=> FromZeros for $atomics [$primitives]); 405 impl_for_transmute_from!(=> FromBytes for $atomics [$primitives]); 406 impl_for_transmute_from!(=> TryFromBytes for $atomics [$primitives]); 407 impl_for_transmute_from!(=> IntoBytes for $atomics [$primitives]); 408 )* 409 }; 410 } 411 412 /// Implements `TransmuteFrom` for `$atomic`, `$prim`, and 413 /// `UnsafeCell<$prim>`. 414 /// 415 /// # Safety 416 /// 417 /// `$atomic` must have the same size and bit validity as `$prim`. 418 macro_rules! unsafe_impl_transmute_from_for_atomic { 419 ($($($tyvar:ident)? => $atomic:ty [$prim:ty]),*) => {{ 420 crate::util::macros::__unsafe(); 421 422 use crate::pointer::{SizeEq, TransmuteFrom, invariant::Valid}; 423 424 $( 425 // SAFETY: The caller promised that `$atomic` and `$prim` have 426 // the same size and bit validity. 427 unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for $prim {} 428 // SAFETY: The caller promised that `$atomic` and `$prim` have 429 // the same size and bit validity. 430 unsafe impl<$($tyvar)?> TransmuteFrom<$prim, Valid, Valid> for $atomic {} 431 432 impl<$($tyvar)?> SizeEq<ReadOnly<$atomic>> for ReadOnly<$prim> { 433 type CastFrom = $crate::pointer::cast::CastSizedExact; 434 } 435 436 // SAFETY: The caller promised that `$atomic` and `$prim` have 437 // the same bit validity. `UnsafeCell<T>` has the same bit 438 // validity as `T` [1]. 439 // 440 // [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout: 441 // 442 // `UnsafeCell<T>` has the same in-memory representation as 443 // its inner type `T`. A consequence of this guarantee is that 444 // it is possible to convert between `T` and `UnsafeCell<T>`. 445 unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for core::cell::UnsafeCell<$prim> {} 446 // SAFETY: See previous safety comment. 447 unsafe impl<$($tyvar)?> TransmuteFrom<core::cell::UnsafeCell<$prim>, Valid, Valid> for $atomic {} 448 )* 449 }}; 450 } 451 452 #[cfg(target_has_atomic = "8")] 453 #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "8")))] 454 mod atomic_8 { 455 use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU8}; 456 457 use super::*; 458 459 impl_traits_for_atomics!(AtomicU8[u8], AtomicI8[i8]); 460 461 impl_known_layout!(AtomicBool); 462 impl_for_transmute_from!(=> FromZeros for AtomicBool [bool]); 463 impl_for_transmute_from!(=> TryFromBytes for AtomicBool [bool]); 464 impl_for_transmute_from!(=> IntoBytes for AtomicBool [bool]); 465 466 // SAFETY: Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the 467 // same size as `bool`, `u8`, and `i8` respectively. Since a type's 468 // alignment cannot be smaller than 1 [2], and since its alignment 469 // cannot be greater than its size [3], the only possible value for the 470 // alignment is 1. Thus, it is sound to implement `Unaligned`. 471 // 472 // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU8.html: 473 // 474 // This type has the same size, alignment, and bit validity as the 475 // underlying integer type 476 // 477 // [2] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: 478 // 479 // Alignment is measured in bytes, and must be at least 1. 480 // 481 // [3] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: 482 // 483 // The size of a value is always a multiple of its alignment. 484 #[allow(clippy::multiple_unsafe_ops_per_block)] 485 const _: () = unsafe { 486 unsafe_impl!(AtomicBool: Unaligned); 487 unsafe_impl!(AtomicU8: Unaligned); 488 unsafe_impl!(AtomicI8: Unaligned); 489 assert_unaligned!(AtomicBool, AtomicU8, AtomicI8); 490 }; 491 492 // SAFETY: `AtomicU8`, `AtomicI8`, and `AtomicBool` have the same size 493 // and bit validity as `u8`, `i8`, and `bool` respectively [1][2][3]. 494 // 495 // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU8.html: 496 // 497 // This type has the same size, alignment, and bit validity as the 498 // underlying integer type, `u8`. 499 // 500 // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI8.html: 501 // 502 // This type has the same size, alignment, and bit validity as the 503 // underlying integer type, `i8`. 504 // 505 // [3] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicBool.html: 506 // 507 // This type has the same size, alignment, and bit validity a `bool`. 508 #[allow(clippy::multiple_unsafe_ops_per_block)] 509 const _: () = unsafe { 510 unsafe_impl_transmute_from_for_atomic!( 511 => AtomicU8 [u8], 512 => AtomicI8 [i8], 513 => AtomicBool [bool] 514 ) 515 }; 516 } 517 518 #[cfg(target_has_atomic = "16")] 519 #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "16")))] 520 mod atomic_16 { 521 use core::sync::atomic::{AtomicI16, AtomicU16}; 522 523 use super::*; 524 525 impl_traits_for_atomics!(AtomicU16[u16], AtomicI16[i16]); 526 527 // SAFETY: `AtomicU16` and `AtomicI16` have the same size and bit 528 // validity as `u16` and `i16` respectively [1][2]. 529 // 530 // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU16.html: 531 // 532 // This type has the same size and bit validity as the underlying 533 // integer type, `u16`. 534 // 535 // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI16.html: 536 // 537 // This type has the same size and bit validity as the underlying 538 // integer type, `i16`. 539 #[allow(clippy::multiple_unsafe_ops_per_block)] 540 const _: () = unsafe { 541 unsafe_impl_transmute_from_for_atomic!(=> AtomicU16 [u16], => AtomicI16 [i16]) 542 }; 543 } 544 545 #[cfg(target_has_atomic = "32")] 546 #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "32")))] 547 mod atomic_32 { 548 use core::sync::atomic::{AtomicI32, AtomicU32}; 549 550 use super::*; 551 552 impl_traits_for_atomics!(AtomicU32[u32], AtomicI32[i32]); 553 554 // SAFETY: `AtomicU32` and `AtomicI32` have the same size and bit 555 // validity as `u32` and `i32` respectively [1][2]. 556 // 557 // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU32.html: 558 // 559 // This type has the same size and bit validity as the underlying 560 // integer type, `u32`. 561 // 562 // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI32.html: 563 // 564 // This type has the same size and bit validity as the underlying 565 // integer type, `i32`. 566 #[allow(clippy::multiple_unsafe_ops_per_block)] 567 const _: () = unsafe { 568 unsafe_impl_transmute_from_for_atomic!(=> AtomicU32 [u32], => AtomicI32 [i32]) 569 }; 570 } 571 572 #[cfg(target_has_atomic = "64")] 573 #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "64")))] 574 mod atomic_64 { 575 use core::sync::atomic::{AtomicI64, AtomicU64}; 576 577 use super::*; 578 579 impl_traits_for_atomics!(AtomicU64[u64], AtomicI64[i64]); 580 581 // SAFETY: `AtomicU64` and `AtomicI64` have the same size and bit 582 // validity as `u64` and `i64` respectively [1][2]. 583 // 584 // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU64.html: 585 // 586 // This type has the same size and bit validity as the underlying 587 // integer type, `u64`. 588 // 589 // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI64.html: 590 // 591 // This type has the same size and bit validity as the underlying 592 // integer type, `i64`. 593 #[allow(clippy::multiple_unsafe_ops_per_block)] 594 const _: () = unsafe { 595 unsafe_impl_transmute_from_for_atomic!(=> AtomicU64 [u64], => AtomicI64 [i64]) 596 }; 597 } 598 599 #[cfg(target_has_atomic = "ptr")] 600 #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "ptr")))] 601 mod atomic_ptr { 602 use core::sync::atomic::{AtomicIsize, AtomicPtr, AtomicUsize}; 603 604 use super::*; 605 606 impl_traits_for_atomics!(AtomicUsize[usize], AtomicIsize[isize]); 607 608 // FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement 609 // those traits for `*mut T`. 610 impl_known_layout!(T => AtomicPtr<T>); 611 impl_for_transmute_from!(T => TryFromBytes for AtomicPtr<T> [*mut T]); 612 impl_for_transmute_from!(T => FromZeros for AtomicPtr<T> [*mut T]); 613 614 // SAFETY: `AtomicUsize` and `AtomicIsize` have the same size and bit 615 // validity as `usize` and `isize` respectively [1][2]. 616 // 617 // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicUsize.html: 618 // 619 // This type has the same size and bit validity as the underlying 620 // integer type, `usize`. 621 // 622 // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicIsize.html: 623 // 624 // This type has the same size and bit validity as the underlying 625 // integer type, `isize`. 626 #[allow(clippy::multiple_unsafe_ops_per_block)] 627 const _: () = unsafe { 628 unsafe_impl_transmute_from_for_atomic!(=> AtomicUsize [usize], => AtomicIsize [isize]) 629 }; 630 631 // SAFETY: Per 632 // https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicPtr.html: 633 // 634 // This type has the same size and bit validity as a `*mut T`. 635 #[allow(clippy::multiple_unsafe_ops_per_block)] 636 const _: () = unsafe { unsafe_impl_transmute_from_for_atomic!(T => AtomicPtr<T> [*mut T]) }; 637 } 638 } 639 640 // SAFETY: Per reference [1]: "For all T, the following are guaranteed: 641 // size_of::<PhantomData<T>>() == 0 align_of::<PhantomData<T>>() == 1". This 642 // gives: 643 // - `Immutable`: `PhantomData` has no fields. 644 // - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: There is only 645 // one possible sequence of 0 bytes, and `PhantomData` is inhabited. 646 // - `IntoBytes`: Since `PhantomData` has size 0, it contains no padding bytes. 647 // - `Unaligned`: Per the preceding reference, `PhantomData` has alignment 1. 648 // 649 // [1] https://doc.rust-lang.org/1.81.0/std/marker/struct.PhantomData.html#layout-1 650 #[allow(clippy::multiple_unsafe_ops_per_block)] 651 const _: () = unsafe { 652 unsafe_impl!(T: ?Sized => Immutable for PhantomData<T>); 653 unsafe_impl!(T: ?Sized => TryFromBytes for PhantomData<T>); 654 unsafe_impl!(T: ?Sized => FromZeros for PhantomData<T>); 655 unsafe_impl!(T: ?Sized => FromBytes for PhantomData<T>); 656 unsafe_impl!(T: ?Sized => IntoBytes for PhantomData<T>); 657 unsafe_impl!(T: ?Sized => Unaligned for PhantomData<T>); 658 assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>); 659 }; 660 661 impl_for_transmute_from!(T: TryFromBytes => TryFromBytes for Wrapping<T>[T]); 662 impl_for_transmute_from!(T: FromZeros => FromZeros for Wrapping<T>[T]); 663 impl_for_transmute_from!(T: FromBytes => FromBytes for Wrapping<T>[T]); 664 impl_for_transmute_from!(T: IntoBytes => IntoBytes for Wrapping<T>[T]); 665 assert_unaligned!(Wrapping<()>, Wrapping<u8>); 666 667 // SAFETY: Per [1], `Wrapping<T>` has the same layout as `T`. Since its single 668 // field (of type `T`) is public, it would be a breaking change to add or remove 669 // fields. Thus, we know that `Wrapping<T>` contains a `T` (as opposed to just 670 // having the same size and alignment as `T`) with no pre- or post-padding. 671 // Thus, `Wrapping<T>` must have `UnsafeCell`s covering the same byte ranges as 672 // `Inner = T`. 673 // 674 // [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: 675 // 676 // `Wrapping<T>` is guaranteed to have the same layout and ABI as `T` 677 const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for Wrapping<T>) }; 678 679 // SAFETY: Per [1] in the preceding safety comment, `Wrapping<T>` has the same 680 // alignment as `T`. 681 const _: () = unsafe { unsafe_impl!(T: Unaligned => Unaligned for Wrapping<T>) }; 682 683 // SAFETY: `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: 684 // `MaybeUninit<T>` has no restrictions on its contents. 685 #[allow(clippy::multiple_unsafe_ops_per_block)] 686 const _: () = unsafe { 687 unsafe_impl!(T => TryFromBytes for CoreMaybeUninit<T>); 688 unsafe_impl!(T => FromZeros for CoreMaybeUninit<T>); 689 unsafe_impl!(T => FromBytes for CoreMaybeUninit<T>); 690 }; 691 692 // SAFETY: `MaybeUninit<T>` has `UnsafeCell`s covering the same byte ranges as 693 // `Inner = T`. This is not explicitly documented, but it can be inferred. Per 694 // [1], `MaybeUninit<T>` has the same size as `T`. Further, note the signature 695 // of `MaybeUninit::assume_init_ref` [2]: 696 // 697 // pub unsafe fn assume_init_ref(&self) -> &T 698 // 699 // If the argument `&MaybeUninit<T>` and the returned `&T` had `UnsafeCell`s at 700 // different offsets, this would be unsound. Its existence is proof that this is 701 // not the case. 702 // 703 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: 704 // 705 // `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as 706 // `T`. 707 // 708 // [2] https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#method.assume_init_ref 709 const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for CoreMaybeUninit<T>) }; 710 711 // SAFETY: Per [1] in the preceding safety comment, `MaybeUninit<T>` has the 712 // same alignment as `T`. 713 const _: () = unsafe { unsafe_impl!(T: Unaligned => Unaligned for CoreMaybeUninit<T>) }; 714 assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit<u8>); 715 716 // SAFETY: `ManuallyDrop<T>` has the same layout as `T` [1]. This strongly 717 // implies, but does not guarantee, that it contains `UnsafeCell`s covering the 718 // same byte ranges as in `T`. However, it also implements `Defer<Target = T>` 719 // [2], which provides the ability to convert `&ManuallyDrop<T> -> &T`. This, 720 // combined with having the same size as `T`, implies that `ManuallyDrop<T>` 721 // exactly contains a `T` with the same fields and `UnsafeCell`s covering the 722 // same byte ranges, or else the `Deref` impl would permit safe code to obtain 723 // different shared references to the same region of memory with different 724 // `UnsafeCell` coverage, which would in turn permit interior mutation that 725 // would violate the invariants of a shared reference. 726 // 727 // [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: 728 // 729 // `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as 730 // `T` 731 // 732 // [2] https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E 733 const _: () = unsafe { unsafe_impl!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>) }; 734 735 impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>[T]); 736 impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>[T]); 737 impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>[T]); 738 impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[T]); 739 // SAFETY: `ManuallyDrop<T>` has the same layout as `T` [1], and thus has the 740 // same alignment as `T`. 741 // 742 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: 743 // 744 // `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as 745 // `T` 746 const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>) }; 747 assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>); 748 749 const _: () = { 750 #[allow( 751 non_camel_case_types, 752 missing_copy_implementations, 753 missing_debug_implementations, 754 missing_docs 755 )] 756 pub enum value {} 757 758 // SAFETY: See safety comment on `ProjectToTag`. 759 unsafe impl<T: ?Sized> HasTag for ManuallyDrop<T> { 760 #[inline] 761 fn only_derive_is_allowed_to_implement_this_trait() 762 where 763 Self: Sized, 764 { 765 } 766 767 type Tag = (); 768 769 // SAFETY: It is trivially sound to project any pointer to a pointer to 770 // a type of size zero and alignment 1 (which `()` is [1]). Such a 771 // pointer will trivially satisfy its aliasing and validity requirements 772 // (since it has a zero-sized referent), and its alignment requirement 773 // (since it is aligned to 1). 774 // 775 // [1] Per https://doc.rust-lang.org/1.92.0/reference/type-layout.html#r-layout.tuple.unit: 776 // 777 // [T]he unit tuple (`()`)... is guaranteed as a zero-sized type to 778 // have a size of 0 and an alignment of 1. 779 type ProjectToTag = crate::pointer::cast::CastToUnit; 780 } 781 782 // SAFETY: `ManuallyDrop<T>` has a field of type `T` at offset `0` without 783 // any safety invariants beyond those of `T`. Its existence is not 784 // explicitly documented, but it can be inferred; per [1] `ManuallyDrop<T>` 785 // has the same size and bit validity as `T`. This field is not literally 786 // public, but is effectively so; the field can be transparently: 787 // 788 // - initialized via `ManuallyDrop::new` 789 // - moved via `ManuallyDrop::into_inner` 790 // - referenced via `ManuallyDrop::deref` 791 // - exclusively referenced via `ManuallyDrop::deref_mut` 792 // 793 // We call this field `value`, both because that is both the name of this 794 // private field, and because it is the name it is referred to in the public 795 // documentation of `ManuallyDrop::new`, `ManuallyDrop::into_inner`, 796 // `ManuallyDrop::take` and `ManuallyDrop::drop`. 797 unsafe impl<T: ?Sized> 798 HasField<value, { crate::STRUCT_VARIANT_ID }, { crate::ident_id!(value) }> 799 for ManuallyDrop<T> 800 { 801 #[inline] 802 fn only_derive_is_allowed_to_implement_this_trait() 803 where 804 Self: Sized, 805 { 806 } 807 808 type Type = T; 809 810 #[inline(always)] 811 fn project(slf: PtrInner<'_, Self>) -> *mut T { 812 // SAFETY: `ManuallyDrop<T>` has the same layout and bit validity as 813 // `T` [1]. 814 // 815 // [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: 816 // 817 // `ManuallyDrop<T>` is guaranteed to have the same layout and bit 818 // validity as `T` 819 #[allow(clippy::as_conversions)] 820 return slf.as_ptr() as *mut T; 821 } 822 } 823 }; 824 825 impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for Cell<T>[T]); 826 impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for Cell<T>[T]); 827 impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for Cell<T>[T]); 828 impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for Cell<T>[T]); 829 // SAFETY: `Cell<T>` has the same in-memory representation as `T` [1], and thus 830 // has the same alignment as `T`. 831 // 832 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.Cell.html#memory-layout: 833 // 834 // `Cell<T>` has the same in-memory representation as its inner type `T`. 835 const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for Cell<T>) }; 836 837 impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for UnsafeCell<T>[T]); 838 impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for UnsafeCell<T>[T]); 839 impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>[T]); 840 // SAFETY: `UnsafeCell<T>` has the same in-memory representation as `T` [1], and 841 // thus has the same alignment as `T`. 842 // 843 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: 844 // 845 // `UnsafeCell<T>` has the same in-memory representation as its inner type 846 // `T`. 847 const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>) }; 848 assert_unaligned!(UnsafeCell<()>, UnsafeCell<u8>); 849 850 // SAFETY: See safety comment in `is_bit_valid` impl. 851 unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> { 852 #[allow(clippy::missing_inline_in_public_items)] 853 fn only_derive_is_allowed_to_implement_this_trait() 854 where 855 Self: Sized, 856 { 857 } 858 859 #[inline(always)] 860 fn is_bit_valid<A>(candidate: Maybe<'_, Self, A>) -> bool 861 where 862 A: invariant::Alignment, 863 { 864 T::is_bit_valid(candidate.transmute::<_, _, BecauseImmutable>()) 865 } 866 } 867 868 // SAFETY: Per the reference [1]: 869 // 870 // An array of `[T; N]` has a size of `size_of::<T>() * N` and the same 871 // alignment of `T`. Arrays are laid out so that the zero-based `nth` element 872 // of the array is offset from the start of the array by `n * size_of::<T>()` 873 // bytes. 874 // 875 // ... 876 // 877 // Slices have the same layout as the section of the array they slice. 878 // 879 // In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s laid 880 // out back-to-back with no bytes in between. Therefore, `[T]` or `[T; N]` are 881 // `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, and `IntoBytes` if `T` 882 // is (respectively). Furthermore, since an array/slice has "the same alignment 883 // of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is. 884 // 885 // Note that we don't `assert_unaligned!` for slice types because 886 // `assert_unaligned!` uses `align_of`, which only works for `Sized` types. 887 // 888 // [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#array-layout 889 #[allow(clippy::multiple_unsafe_ops_per_block)] 890 const _: () = unsafe { 891 unsafe_impl!(const N: usize, T: Immutable => Immutable for [T; N]); 892 unsafe_impl!(const N: usize, T: TryFromBytes => TryFromBytes for [T; N]; |c| { 893 let c: Ptr<'_, [ReadOnly<T>; N], _> = c.cast::<_, crate::pointer::cast::CastSized, _>(); 894 let c: Ptr<'_, [ReadOnly<T>], _> = c.as_slice(); 895 let c: Ptr<'_, ReadOnly<[T]>, _> = c.cast::<_, crate::pointer::cast::CastUnsized, _>(); 896 897 // Note that this call may panic, but it would still be sound even if it 898 // did. `is_bit_valid` does not promise that it will not panic (in fact, 899 // it explicitly warns that it's a possibility), and we have not 900 // violated any safety invariants that we must fix before returning. 901 <[T] as TryFromBytes>::is_bit_valid(c) 902 }); 903 unsafe_impl!(const N: usize, T: FromZeros => FromZeros for [T; N]); 904 unsafe_impl!(const N: usize, T: FromBytes => FromBytes for [T; N]); 905 unsafe_impl!(const N: usize, T: IntoBytes => IntoBytes for [T; N]); 906 unsafe_impl!(const N: usize, T: Unaligned => Unaligned for [T; N]); 907 assert_unaligned!([(); 0], [(); 1], [u8; 0], [u8; 1]); 908 unsafe_impl!(T: Immutable => Immutable for [T]); 909 unsafe_impl!(T: TryFromBytes => TryFromBytes for [T]; |c| { 910 let c: Ptr<'_, [ReadOnly<T>], _> = c.cast::<_, crate::pointer::cast::CastUnsized, _>(); 911 912 // SAFETY: Per the reference [1]: 913 // 914 // An array of `[T; N]` has a size of `size_of::<T>() * N` and the 915 // same alignment of `T`. Arrays are laid out so that the zero-based 916 // `nth` element of the array is offset from the start of the array by 917 // `n * size_of::<T>()` bytes. 918 // 919 // ... 920 // 921 // Slices have the same layout as the section of the array they slice. 922 // 923 // In other words, the layout of a `[T] is a sequence of `T`s laid out 924 // back-to-back with no bytes in between. If all elements in `candidate` 925 // are `is_bit_valid`, so too is `candidate`. 926 // 927 // Note that any of the below calls may panic, but it would still be 928 // sound even if it did. `is_bit_valid` does not promise that it will 929 // not panic (in fact, it explicitly warns that it's a possibility), and 930 // we have not violated any safety invariants that we must fix before 931 // returning. 932 c.iter().all(<T as TryFromBytes>::is_bit_valid) 933 }); 934 unsafe_impl!(T: FromZeros => FromZeros for [T]); 935 unsafe_impl!(T: FromBytes => FromBytes for [T]); 936 unsafe_impl!(T: IntoBytes => IntoBytes for [T]); 937 unsafe_impl!(T: Unaligned => Unaligned for [T]); 938 }; 939 940 // SAFETY: 941 // - `Immutable`: Raw pointers do not contain any `UnsafeCell`s. 942 // - `FromZeros`: For thin pointers (note that `T: Sized`), the zero pointer is 943 // considered "null". [1] No operations which require provenance are legal on 944 // null pointers, so this is not a footgun. 945 // - `TryFromBytes`: By the same reasoning as for `FromZeroes`, we can implement 946 // `TryFromBytes` for thin pointers provided that 947 // [`TryFromByte::is_bit_valid`] only produces `true` for zeroed bytes. 948 // 949 // NOTE(#170): Implementing `FromBytes` and `IntoBytes` for raw pointers would 950 // be sound, but carries provenance footguns. We want to support `FromBytes` and 951 // `IntoBytes` for raw pointers eventually, but we are holding off until we can 952 // figure out how to address those footguns. 953 // 954 // [1] Per https://doc.rust-lang.org/1.81.0/std/ptr/fn.null.html: 955 // 956 // Creates a null raw pointer. 957 // 958 // This function is equivalent to zero-initializing the pointer: 959 // `MaybeUninit::<*const T>::zeroed().assume_init()`. 960 // 961 // The resulting pointer has the address 0. 962 #[allow(clippy::multiple_unsafe_ops_per_block)] 963 const _: () = unsafe { 964 unsafe_impl!(T: ?Sized => Immutable for *const T); 965 unsafe_impl!(T: ?Sized => Immutable for *mut T); 966 unsafe_impl!(T => TryFromBytes for *const T; |c| pointer::is_zeroed(c)); 967 unsafe_impl!(T => FromZeros for *const T); 968 unsafe_impl!(T => TryFromBytes for *mut T; |c| pointer::is_zeroed(c)); 969 unsafe_impl!(T => FromZeros for *mut T); 970 }; 971 972 // SAFETY: `NonNull<T>` self-evidently does not contain `UnsafeCell`s. This is 973 // not a proof, but we are accepting this as a known risk per #1358. 974 const _: () = unsafe { unsafe_impl!(T: ?Sized => Immutable for NonNull<T>) }; 975 976 // SAFETY: Reference types do not contain any `UnsafeCell`s. 977 #[allow(clippy::multiple_unsafe_ops_per_block)] 978 const _: () = unsafe { 979 unsafe_impl!(T: ?Sized => Immutable for &'_ T); 980 unsafe_impl!(T: ?Sized => Immutable for &'_ mut T); 981 }; 982 983 // SAFETY: `Option` is not `#[non_exhaustive]` [1], which means that the types 984 // in its variants cannot change, and no new variants can be added. `Option<T>` 985 // does not contain any `UnsafeCell`s outside of `T`. [1] 986 // 987 // [1] https://doc.rust-lang.org/core/option/enum.Option.html 988 const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for Option<T>) }; 989 990 mod tuples { 991 use super::*; 992 993 /// Generates various trait implementations for tuples. 994 /// 995 /// # Safety 996 /// 997 /// `impl_tuple!` should be provided name-number pairs, where each number is 998 /// the ordinal of the preceding type name. 999 macro_rules! impl_tuple { 1000 // Entry point. 1001 ($($T:ident $I:tt),+ $(,)?) => { 1002 crate::util::macros::__unsafe(); 1003 impl_tuple!(@all [] [$($T $I)+]); 1004 }; 1005 1006 // Build up the set of tuple types (i.e., `(A,)`, `(A, B)`, `(A, B, C)`, 1007 // etc.) Trait implementations that do not depend on field index may be 1008 // added to this branch. 1009 (@all [$($head_T:ident $head_I:tt)*] [$next_T:ident $next_I:tt $($tail:tt)*]) => { 1010 // SAFETY: If all fields of the tuple `Self` are `Immutable`, so too is `Self`. 1011 unsafe_impl!($($head_T: Immutable,)* $next_T: Immutable => Immutable for ($($head_T,)* $next_T,)); 1012 1013 // SAFETY: If all fields in `c` are `is_bit_valid`, so too is `c`. 1014 unsafe_impl!($($head_T: TryFromBytes,)* $next_T: TryFromBytes => TryFromBytes for ($($head_T,)* $next_T,); |c| { 1015 let mut c = c; 1016 $(TryFromBytes::is_bit_valid(into_inner!(c.reborrow().project::<_, { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($head_I) }>())) &&)* 1017 TryFromBytes::is_bit_valid(into_inner!(c.reborrow().project::<_, { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($next_I) }>())) 1018 }); 1019 1020 // SAFETY: If all fields in `Self` are `FromZeros`, so too is `Self`. 1021 unsafe_impl!($($head_T: FromZeros,)* $next_T: FromZeros => FromZeros for ($($head_T,)* $next_T,)); 1022 1023 // SAFETY: If all fields in `Self` are `FromBytes`, so too is `Self`. 1024 unsafe_impl!($($head_T: FromBytes,)* $next_T: FromBytes => FromBytes for ($($head_T,)* $next_T,)); 1025 1026 // SAFETY: See safety comment on `ProjectToTag`. 1027 unsafe impl<$($head_T,)* $next_T> crate::HasTag for ($($head_T,)* $next_T,) { 1028 #[inline] 1029 fn only_derive_is_allowed_to_implement_this_trait() 1030 where 1031 Self: Sized 1032 {} 1033 1034 type Tag = (); 1035 1036 // SAFETY: It is trivially sound to project any pointer to a 1037 // pointer to a type of size zero and alignment 1 (which `()` is 1038 // [1]). Such a pointer will trivially satisfy its aliasing and 1039 // validity requirements (since it has a zero-sized referent), 1040 // and its alignment requirement (since it is aligned to 1). 1041 // 1042 // [1] Per https://doc.rust-lang.org/1.92.0/reference/type-layout.html#r-layout.tuple.unit: 1043 // 1044 // [T]he unit tuple (`()`)... is guaranteed as a zero-sized 1045 // type to have a size of 0 and an alignment of 1. 1046 type ProjectToTag = crate::pointer::cast::CastToUnit; 1047 } 1048 1049 // Generate impls that depend on tuple index. 1050 impl_tuple!(@variants 1051 [$($head_T $head_I)* $next_T $next_I] 1052 [] 1053 [$($head_T $head_I)* $next_T $next_I] 1054 ); 1055 1056 // Recurse to next tuple size 1057 impl_tuple!(@all [$($head_T $head_I)* $next_T $next_I] [$($tail)*]); 1058 }; 1059 (@all [$($head_T:ident $head_I:tt)*] []) => {}; 1060 1061 // Emit trait implementations that depend on field index. 1062 (@variants 1063 // The full tuple definition in type–index pairs. 1064 [$($AllT:ident $AllI:tt)+] 1065 // Types before the current index. 1066 [$($BeforeT:ident)*] 1067 // The types and indices at and after the current index. 1068 [$CurrT:ident $CurrI:tt $($AfterT:ident $AfterI:tt)*] 1069 ) => { 1070 // SAFETY: 1071 // - `Self` is a struct (albeit anonymous), so `VARIANT_ID` is 1072 // `STRUCT_VARIANT_ID`. 1073 // - `$CurrI` is the field at index `$CurrI`, so `FIELD_ID` is 1074 // `zerocopy::ident_id!($CurrI)` 1075 // - `()` has the same visibility as the `.$CurrI` field (ie, `.0`, 1076 // `.1`, etc) 1077 // - `Type` has the same type as `$CurrI`; i.e., `$CurrT`. 1078 unsafe impl<$($AllT),+> crate::HasField< 1079 (), 1080 { crate::STRUCT_VARIANT_ID }, 1081 { crate::ident_id!($CurrI)} 1082 > for ($($AllT,)+) { 1083 #[inline] 1084 fn only_derive_is_allowed_to_implement_this_trait() 1085 where 1086 Self: Sized 1087 {} 1088 1089 type Type = $CurrT; 1090 1091 #[inline(always)] 1092 fn project(slf: crate::PtrInner<'_, Self>) -> *mut Self::Type { 1093 let slf = slf.as_non_null().as_ptr(); 1094 // SAFETY: `PtrInner` promises it references either a zero-sized 1095 // byte range, or else will reference a byte range that is 1096 // entirely contained within an allocated object. In either 1097 // case, this guarantees that `(*slf).$CurrI` is in-bounds of 1098 // `slf`. 1099 unsafe { core::ptr::addr_of_mut!((*slf).$CurrI) } 1100 } 1101 } 1102 1103 // SAFETY: See comments on items. 1104 unsafe impl<Aliasing, Alignment, $($AllT),+> crate::ProjectField< 1105 (), 1106 (Aliasing, Alignment, crate::invariant::Uninit), 1107 { crate::STRUCT_VARIANT_ID }, 1108 { crate::ident_id!($CurrI)} 1109 > for ($($AllT,)+) 1110 where 1111 Aliasing: crate::invariant::Aliasing, 1112 Alignment: crate::invariant::Alignment, 1113 { 1114 #[inline] 1115 fn only_derive_is_allowed_to_implement_this_trait() 1116 where 1117 Self: Sized 1118 {} 1119 1120 // SAFETY: Tuples are product types whose fields are 1121 // well-aligned, so projection preserves both the alignment and 1122 // validity invariants of the outer pointer. 1123 type Invariants = (Aliasing, Alignment, crate::invariant::Uninit); 1124 1125 // SAFETY: Tuples are product types and so projection is infallible; 1126 type Error = core::convert::Infallible; 1127 } 1128 1129 // SAFETY: See comments on items. 1130 unsafe impl<Aliasing, Alignment, $($AllT),+> crate::ProjectField< 1131 (), 1132 (Aliasing, Alignment, crate::invariant::Initialized), 1133 { crate::STRUCT_VARIANT_ID }, 1134 { crate::ident_id!($CurrI)} 1135 > for ($($AllT,)+) 1136 where 1137 Aliasing: crate::invariant::Aliasing, 1138 Alignment: crate::invariant::Alignment, 1139 { 1140 #[inline] 1141 fn only_derive_is_allowed_to_implement_this_trait() 1142 where 1143 Self: Sized 1144 {} 1145 1146 // SAFETY: Tuples are product types whose fields are 1147 // well-aligned, so projection preserves both the alignment and 1148 // validity invariants of the outer pointer. 1149 type Invariants = (Aliasing, Alignment, crate::invariant::Initialized); 1150 1151 // SAFETY: Tuples are product types and so projection is infallible; 1152 type Error = core::convert::Infallible; 1153 } 1154 1155 // SAFETY: See comments on items. 1156 unsafe impl<Aliasing, Alignment, $($AllT),+> crate::ProjectField< 1157 (), 1158 (Aliasing, Alignment, crate::invariant::Valid), 1159 { crate::STRUCT_VARIANT_ID }, 1160 { crate::ident_id!($CurrI)} 1161 > for ($($AllT,)+) 1162 where 1163 Aliasing: crate::invariant::Aliasing, 1164 Alignment: crate::invariant::Alignment, 1165 { 1166 #[inline] 1167 fn only_derive_is_allowed_to_implement_this_trait() 1168 where 1169 Self: Sized 1170 {} 1171 1172 // SAFETY: Tuples are product types whose fields are 1173 // well-aligned, so projection preserves both the alignment and 1174 // validity invariants of the outer pointer. 1175 type Invariants = (Aliasing, Alignment, crate::invariant::Valid); 1176 1177 // SAFETY: Tuples are product types and so projection is infallible; 1178 type Error = core::convert::Infallible; 1179 } 1180 1181 // Recurse to the next index. 1182 impl_tuple!(@variants [$($AllT $AllI)+] [$($BeforeT)* $CurrT] [$($AfterT $AfterI)*]); 1183 }; 1184 (@variants [$($AllT:ident $AllI:tt)+] [$($BeforeT:ident)*] []) => {}; 1185 } 1186 1187 // SAFETY: `impl_tuple` is provided name-number pairs, where number is the 1188 // ordinal of the name. 1189 #[allow(clippy::multiple_unsafe_ops_per_block)] 1190 const _: () = unsafe { 1191 impl_tuple! { 1192 A 0, 1193 B 1, 1194 C 2, 1195 D 3, 1196 E 4, 1197 F 5, 1198 G 6, 1199 H 7, 1200 I 8, 1201 J 9, 1202 K 10, 1203 L 11, 1204 M 12, 1205 N 13, 1206 O 14, 1207 P 15, 1208 Q 16, 1209 R 17, 1210 S 18, 1211 T 19, 1212 U 20, 1213 V 21, 1214 W 22, 1215 X 23, 1216 Y 24, 1217 Z 25, 1218 }; 1219 }; 1220 } 1221 1222 // SIMD support 1223 // 1224 // Per the Unsafe Code Guidelines Reference [1]: 1225 // 1226 // Packed SIMD vector types are `repr(simd)` homogeneous tuple-structs 1227 // containing `N` elements of type `T` where `N` is a power-of-two and the 1228 // size and alignment requirements of `T` are equal: 1229 // 1230 // ```rust 1231 // #[repr(simd)] 1232 // struct Vector<T, N>(T_0, ..., T_(N - 1)); 1233 // ``` 1234 // 1235 // ... 1236 // 1237 // The size of `Vector` is `N * size_of::<T>()` and its alignment is an 1238 // implementation-defined function of `T` and `N` greater than or equal to 1239 // `align_of::<T>()`. 1240 // 1241 // ... 1242 // 1243 // Vector elements are laid out in source field order, enabling random access 1244 // to vector elements by reinterpreting the vector as an array: 1245 // 1246 // ```rust 1247 // union U { 1248 // vec: Vector<T, N>, 1249 // arr: [T; N] 1250 // } 1251 // 1252 // assert_eq!(size_of::<Vector<T, N>>(), size_of::<[T; N]>()); 1253 // assert!(align_of::<Vector<T, N>>() >= align_of::<[T; N]>()); 1254 // 1255 // unsafe { 1256 // let u = U { vec: Vector<T, N>(t_0, ..., t_(N - 1)) }; 1257 // 1258 // assert_eq!(u.vec.0, u.arr[0]); 1259 // // ... 1260 // assert_eq!(u.vec.(N - 1), u.arr[N - 1]); 1261 // } 1262 // ``` 1263 // 1264 // Given this background, we can observe that: 1265 // - The size and bit pattern requirements of a SIMD type are equivalent to the 1266 // equivalent array type. Thus, for any SIMD type whose primitive `T` is 1267 // `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, or `IntoBytes`, that 1268 // SIMD type is also `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, or 1269 // `IntoBytes` respectively. 1270 // - Since no upper bound is placed on the alignment, no SIMD type can be 1271 // guaranteed to be `Unaligned`. 1272 // 1273 // Also per [1]: 1274 // 1275 // This chapter represents the consensus from issue #38. The statements in 1276 // here are not (yet) "guaranteed" not to change until an RFC ratifies them. 1277 // 1278 // See issue #38 [2]. While this behavior is not technically guaranteed, the 1279 // likelihood that the behavior will change such that SIMD types are no longer 1280 // `TryFromBytes`, `FromZeros`, `FromBytes`, or `IntoBytes` is next to zero, as 1281 // that would defeat the entire purpose of SIMD types. Nonetheless, we put this 1282 // behavior behind the `simd` Cargo feature, which requires consumers to opt 1283 // into this stability hazard. 1284 // 1285 // [1] https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html 1286 // [2] https://github.com/rust-lang/unsafe-code-guidelines/issues/38 1287 #[cfg(feature = "simd")] 1288 #[cfg_attr(doc_cfg, doc(cfg(feature = "simd")))] 1289 mod simd { 1290 /// Defines a module which implements `TryFromBytes`, `FromZeros`, 1291 /// `FromBytes`, and `IntoBytes` for a set of types from a module in 1292 /// `core::arch`. 1293 /// 1294 /// `$arch` is both the name of the defined module and the name of the 1295 /// module in `core::arch`, and `$typ` is the list of items from that module 1296 /// to implement `FromZeros`, `FromBytes`, and `IntoBytes` for. 1297 #[allow(unused_macros)] // `allow(unused_macros)` is needed because some 1298 // target/feature combinations don't emit any impls 1299 // and thus don't use this macro. 1300 macro_rules! simd_arch_mod { 1301 ($(#[cfg $cfg:tt])* $(#[cfg_attr $cfg_attr:tt])? $arch:ident, $mod:ident, $($typ:ident),*) => { 1302 $(#[cfg $cfg])* 1303 #[cfg_attr(doc_cfg, doc(cfg $($cfg)*))] 1304 $(#[cfg_attr $cfg_attr])? 1305 mod $mod { 1306 use core::arch::$arch::{$($typ),*}; 1307 1308 use crate::*; 1309 impl_known_layout!($($typ),*); 1310 // SAFETY: See comment on module definition for justification. 1311 #[allow(clippy::multiple_unsafe_ops_per_block)] 1312 const _: () = unsafe { 1313 $( unsafe_impl!($typ: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); )* 1314 }; 1315 } 1316 }; 1317 } 1318 1319 #[rustfmt::skip] 1320 const _: () = { 1321 simd_arch_mod!( 1322 #[cfg(target_arch = "x86")] 1323 x86, x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i 1324 ); 1325 #[cfg(not(no_zerocopy_simd_x86_avx12_1_89_0))] 1326 simd_arch_mod!( 1327 #[cfg(target_arch = "x86")] 1328 #[cfg_attr(doc_cfg, doc(cfg(rust = "1.89.0")))] 1329 x86, x86_nightly, __m512bh, __m512, __m512d, __m512i 1330 ); 1331 simd_arch_mod!( 1332 #[cfg(target_arch = "x86_64")] 1333 x86_64, x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i 1334 ); 1335 #[cfg(not(no_zerocopy_simd_x86_avx12_1_89_0))] 1336 simd_arch_mod!( 1337 #[cfg(target_arch = "x86_64")] 1338 #[cfg_attr(doc_cfg, doc(cfg(rust = "1.89.0")))] 1339 x86_64, x86_64_nightly, __m512bh, __m512, __m512d, __m512i 1340 ); 1341 simd_arch_mod!( 1342 #[cfg(target_arch = "wasm32")] 1343 wasm32, wasm32, v128 1344 ); 1345 simd_arch_mod!( 1346 #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))] 1347 powerpc, powerpc, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long 1348 ); 1349 simd_arch_mod!( 1350 #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))] 1351 powerpc64, powerpc64, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long 1352 ); 1353 // NOTE: NEON intrinsics were broken on big-endian platforms from their stabilization up to 1354 // Rust 1.87. (Context in https://github.com/rust-lang/stdarch/issues/1484). Support is 1355 // split in two different version ranges on top of the base configuration, requiring either 1356 // little endian or the more recent version to be detected as well. 1357 #[cfg(not(no_zerocopy_aarch64_simd_1_59_0))] 1358 simd_arch_mod!( 1359 #[cfg(all( 1360 target_arch = "aarch64", 1361 any( 1362 target_endian = "little", 1363 not(no_zerocopy_aarch64_simd_be_1_87_0) 1364 ) 1365 ))] 1366 #[cfg_attr( 1367 doc_cfg, 1368 doc(cfg(all(target_arch = "aarch64", any( 1369 all(rust = "1.59.0", target_endian = "little"), 1370 rust = "1.87.0", 1371 )))) 1372 )] 1373 aarch64, aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t, 1374 int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t, 1375 int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, 1376 poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t, 1377 poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t, 1378 uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x4x2_t, uint16x4x3_t, 1379 uint16x4x4_t, uint16x8_t, uint32x2_t, uint32x4_t, uint64x1_t, uint64x2_t 1380 ); 1381 }; 1382 } 1383 1384 #[cfg(test)] 1385 mod tests { 1386 use super::*; 1387 1388 #[test] 1389 fn test_impls() { 1390 // A type that can supply test cases for testing 1391 // `TryFromBytes::is_bit_valid`. All types passed to `assert_impls!` 1392 // must implement this trait; that macro uses it to generate runtime 1393 // tests for `TryFromBytes` impls. 1394 // 1395 // All `T: FromBytes` types are provided with a blanket impl. Other 1396 // types must implement `TryFromBytesTestable` directly (ie using 1397 // `impl_try_from_bytes_testable!`). 1398 trait TryFromBytesTestable { 1399 fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F); 1400 fn with_failing_test_cases<F: Fn(&mut [u8])>(f: F); 1401 } 1402 1403 impl<T: FromBytes> TryFromBytesTestable for T { 1404 fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F) { 1405 // Test with a zeroed value. 1406 f(ReadOnly::<Self>::new_box_zeroed().unwrap()); 1407 1408 let ffs = { 1409 let mut t = ReadOnly::new(Self::new_zeroed()); 1410 let ptr: *mut T = ReadOnly::as_mut(&mut t); 1411 // SAFETY: `T: FromBytes` 1412 unsafe { ptr::write_bytes(ptr.cast::<u8>(), 0xFF, mem::size_of::<T>()) }; 1413 t 1414 }; 1415 1416 // Test with a value initialized with 0xFF. 1417 f(Box::new(ffs)); 1418 } 1419 1420 fn with_failing_test_cases<F: Fn(&mut [u8])>(_f: F) {} 1421 } 1422 1423 macro_rules! impl_try_from_bytes_testable_for_null_pointer_optimization { 1424 ($($tys:ty),*) => { 1425 $( 1426 impl TryFromBytesTestable for Option<$tys> { 1427 fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F) { 1428 // Test with a zeroed value. 1429 f(Box::new(ReadOnly::new(None))); 1430 } 1431 1432 fn with_failing_test_cases<F: Fn(&mut [u8])>(f: F) { 1433 for pos in 0..mem::size_of::<Self>() { 1434 let mut bytes = [0u8; mem::size_of::<Self>()]; 1435 bytes[pos] = 0x01; 1436 f(&mut bytes[..]); 1437 } 1438 } 1439 } 1440 )* 1441 }; 1442 } 1443 1444 // Implements `TryFromBytesTestable`. 1445 macro_rules! impl_try_from_bytes_testable { 1446 // Base case for recursion (when the list of types has run out). 1447 (=> @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {}; 1448 // Implements for type(s) with no type parameters. 1449 ($ty:ty $(,$tys:ty)* => @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { 1450 impl TryFromBytesTestable for $ty { 1451 impl_try_from_bytes_testable!( 1452 @methods @success $($success_case),* 1453 $(, @failure $($failure_case),*)? 1454 ); 1455 } 1456 impl_try_from_bytes_testable!($($tys),* => @success $($success_case),* $(, @failure $($failure_case),*)?); 1457 }; 1458 // Implements for multiple types with no type parameters. 1459 ($($($ty:ty),* => @success $($success_case:expr), * $(, @failure $($failure_case:expr),*)?;)*) => { 1460 $( 1461 impl_try_from_bytes_testable!($($ty),* => @success $($success_case),* $(, @failure $($failure_case),*)*); 1462 )* 1463 }; 1464 // Implements only the methods; caller must invoke this from inside 1465 // an impl block. 1466 (@methods @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { 1467 fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(_f: F) { 1468 $( 1469 let bx = Box::<Self>::from($success_case); 1470 let ro: Box<ReadOnly<_>> = { 1471 let raw = Box::into_raw(bx); 1472 // SAFETY: `ReadOnly<T>` has the same layout and bit 1473 // validity as `T`. 1474 #[allow(clippy::as_conversions)] 1475 unsafe { Box::from_raw(raw as *mut _) } 1476 }; 1477 _f(ro); 1478 )* 1479 } 1480 1481 fn with_failing_test_cases<F: Fn(&mut [u8])>(_f: F) { 1482 $($( 1483 let mut case = $failure_case; 1484 _f(case.as_mut_bytes()); 1485 )*)? 1486 } 1487 }; 1488 } 1489 1490 impl_try_from_bytes_testable_for_null_pointer_optimization!( 1491 Box<UnsafeCell<NotZerocopy>>, 1492 &'static UnsafeCell<NotZerocopy>, 1493 &'static mut UnsafeCell<NotZerocopy>, 1494 NonNull<UnsafeCell<NotZerocopy>>, 1495 fn(), 1496 FnManyArgs, 1497 extern "C" fn(), 1498 ECFnManyArgs 1499 ); 1500 1501 macro_rules! bx { 1502 ($e:expr) => { 1503 Box::new($e) 1504 }; 1505 } 1506 1507 // Note that these impls are only for types which are not `FromBytes`. 1508 // `FromBytes` types are covered by a preceding blanket impl. 1509 impl_try_from_bytes_testable!( 1510 bool => @success true, false, 1511 @failure 2u8, 3u8, 0xFFu8; 1512 char => @success '\u{0}', '\u{D7FF}', '\u{E000}', '\u{10FFFF}', 1513 @failure 0xD800u32, 0xDFFFu32, 0x110000u32; 1514 str => @success "", "hello", "❤️", 1515 @failure [0, 159, 146, 150]; 1516 [u8] => @success vec![].into_boxed_slice(), vec![0, 1, 2].into_boxed_slice(); 1517 NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, 1518 NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, 1519 NonZeroUsize, NonZeroIsize 1520 => @success Self::new(1).unwrap(), 1521 // Doing this instead of `0` ensures that we always satisfy 1522 // the size and alignment requirements of `Self` (whereas `0` 1523 // may be any integer type with a different size or alignment 1524 // than some `NonZeroXxx` types). 1525 @failure Option::<Self>::None; 1526 [bool; 0] => @success []; 1527 [bool; 1] 1528 => @success [true], [false], 1529 @failure [2u8], [3u8], [0xFFu8]; 1530 [bool] 1531 => @success vec![true, false].into_boxed_slice(), vec![false, true].into_boxed_slice(), 1532 @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; 1533 Unalign<bool> 1534 => @success Unalign::new(false), Unalign::new(true), 1535 @failure 2u8, 0xFFu8; 1536 ManuallyDrop<bool> 1537 => @success ManuallyDrop::new(false), ManuallyDrop::new(true), 1538 @failure 2u8, 0xFFu8; 1539 ManuallyDrop<[u8]> 1540 => @success bx!(ManuallyDrop::new([])), bx!(ManuallyDrop::new([0u8])), bx!(ManuallyDrop::new([0u8, 1u8])); 1541 ManuallyDrop<[bool]> 1542 => @success bx!(ManuallyDrop::new([])), bx!(ManuallyDrop::new([false])), bx!(ManuallyDrop::new([false, true])), 1543 @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; 1544 ManuallyDrop<[UnsafeCell<u8>]> 1545 => @success bx!(ManuallyDrop::new([UnsafeCell::new(0)])), bx!(ManuallyDrop::new([UnsafeCell::new(0), UnsafeCell::new(1)])); 1546 ManuallyDrop<[UnsafeCell<bool>]> 1547 => @success bx!(ManuallyDrop::new([UnsafeCell::new(false)])), bx!(ManuallyDrop::new([UnsafeCell::new(false), UnsafeCell::new(true)])), 1548 @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; 1549 Wrapping<bool> 1550 => @success Wrapping(false), Wrapping(true), 1551 @failure 2u8, 0xFFu8; 1552 *const NotZerocopy 1553 => @success ptr::null::<NotZerocopy>(), 1554 @failure [0x01; mem::size_of::<*const NotZerocopy>()]; 1555 *mut NotZerocopy 1556 => @success ptr::null_mut::<NotZerocopy>(), 1557 @failure [0x01; mem::size_of::<*mut NotZerocopy>()]; 1558 ); 1559 1560 // Use the trick described in [1] to allow us to call methods 1561 // conditional on certain trait bounds. 1562 // 1563 // In all of these cases, methods return `Option<R>`, where `R` is the 1564 // return type of the method we're conditionally calling. The "real" 1565 // implementations (the ones defined in traits using `&self`) return 1566 // `Some`, and the default implementations (the ones defined as inherent 1567 // methods using `&mut self`) return `None`. 1568 // 1569 // [1] https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md 1570 mod autoref_trick { 1571 use super::*; 1572 1573 pub(super) struct AutorefWrapper<T: ?Sized>(pub(super) PhantomData<T>); 1574 1575 pub(super) trait TestIsBitValidShared<T: ?Sized> { 1576 #[allow(clippy::needless_lifetimes)] 1577 fn test_is_bit_valid_shared<'ptr>(&self, candidate: Maybe<'ptr, T>) 1578 -> Option<bool>; 1579 } 1580 1581 impl<T: TryFromBytes + Immutable + ?Sized> TestIsBitValidShared<T> for AutorefWrapper<T> { 1582 #[allow(clippy::needless_lifetimes)] 1583 fn test_is_bit_valid_shared<'ptr>( 1584 &self, 1585 candidate: Maybe<'ptr, T>, 1586 ) -> Option<bool> { 1587 Some(T::is_bit_valid(candidate)) 1588 } 1589 } 1590 1591 pub(super) trait TestTryFromRef<T: ?Sized> { 1592 #[allow(clippy::needless_lifetimes)] 1593 fn test_try_from_ref<'bytes>( 1594 &self, 1595 bytes: &'bytes [u8], 1596 ) -> Option<Option<&'bytes T>>; 1597 } 1598 1599 impl<T: TryFromBytes + Immutable + KnownLayout + ?Sized> TestTryFromRef<T> for AutorefWrapper<T> { 1600 #[allow(clippy::needless_lifetimes)] 1601 fn test_try_from_ref<'bytes>( 1602 &self, 1603 bytes: &'bytes [u8], 1604 ) -> Option<Option<&'bytes T>> { 1605 Some(T::try_ref_from_bytes(bytes).ok()) 1606 } 1607 } 1608 1609 pub(super) trait TestTryFromMut<T: ?Sized> { 1610 #[allow(clippy::needless_lifetimes)] 1611 fn test_try_from_mut<'bytes>( 1612 &self, 1613 bytes: &'bytes mut [u8], 1614 ) -> Option<Option<&'bytes mut T>>; 1615 } 1616 1617 impl<T: TryFromBytes + IntoBytes + KnownLayout + ?Sized> TestTryFromMut<T> for AutorefWrapper<T> { 1618 #[allow(clippy::needless_lifetimes)] 1619 fn test_try_from_mut<'bytes>( 1620 &self, 1621 bytes: &'bytes mut [u8], 1622 ) -> Option<Option<&'bytes mut T>> { 1623 Some(T::try_mut_from_bytes(bytes).ok()) 1624 } 1625 } 1626 1627 pub(super) trait TestTryReadFrom<T> { 1628 fn test_try_read_from(&self, bytes: &[u8]) -> Option<Option<T>>; 1629 } 1630 1631 impl<T: TryFromBytes> TestTryReadFrom<T> for AutorefWrapper<T> { 1632 fn test_try_read_from(&self, bytes: &[u8]) -> Option<Option<T>> { 1633 Some(T::try_read_from_bytes(bytes).ok()) 1634 } 1635 } 1636 1637 pub(super) trait TestAsBytes<T: ?Sized> { 1638 #[allow(clippy::needless_lifetimes)] 1639 fn test_as_bytes<'slf, 't>(&'slf self, t: &'t ReadOnly<T>) -> Option<&'t [u8]>; 1640 } 1641 1642 impl<T: IntoBytes + Immutable + ?Sized> TestAsBytes<T> for AutorefWrapper<T> { 1643 #[allow(clippy::needless_lifetimes)] 1644 fn test_as_bytes<'slf, 't>(&'slf self, t: &'t ReadOnly<T>) -> Option<&'t [u8]> { 1645 Some(t.as_bytes()) 1646 } 1647 } 1648 } 1649 1650 use autoref_trick::*; 1651 1652 // Asserts that `$ty` is one of a list of types which are allowed to not 1653 // provide a "real" implementation for `$fn_name`. Since the 1654 // `autoref_trick` machinery fails silently, this allows us to ensure 1655 // that the "default" impls are only being used for types which we 1656 // expect. 1657 // 1658 // Note that, since this is a runtime test, it is possible to have an 1659 // allowlist which is too restrictive if the function in question is 1660 // never called for a particular type. For example, if `as_bytes` is not 1661 // supported for a particular type, and so `test_as_bytes` returns 1662 // `None`, methods such as `test_try_from_ref` may never be called for 1663 // that type. As a result, it's possible that, for example, adding 1664 // `as_bytes` support for a type would cause other allowlist assertions 1665 // to fail. This means that allowlist assertion failures should not 1666 // automatically be taken as a sign of a bug. 1667 macro_rules! assert_on_allowlist { 1668 ($fn_name:ident($ty:ty) $(: $($tys:ty),*)?) => {{ 1669 use core::any::TypeId; 1670 1671 let allowlist: &[TypeId] = &[ $($(TypeId::of::<$tys>()),*)? ]; 1672 let allowlist_names: &[&str] = &[ $($(stringify!($tys)),*)? ]; 1673 1674 let id = TypeId::of::<$ty>(); 1675 assert!(allowlist.contains(&id), "{} is not on allowlist for {}: {:?}", stringify!($ty), stringify!($fn_name), allowlist_names); 1676 }}; 1677 } 1678 1679 // Asserts that `$ty` implements any `$trait` and doesn't implement any 1680 // `!$trait`. Note that all `$trait`s must come before any `!$trait`s. 1681 // 1682 // For `T: TryFromBytes`, uses `TryFromBytesTestable` to test success 1683 // and failure cases. 1684 macro_rules! assert_impls { 1685 ($ty:ty: TryFromBytes) => { 1686 // "Default" implementations that match the "real" 1687 // implementations defined in the `autoref_trick` module above. 1688 #[allow(unused, non_local_definitions)] 1689 impl AutorefWrapper<$ty> { 1690 #[allow(clippy::needless_lifetimes)] 1691 fn test_is_bit_valid_shared<'ptr>( 1692 &mut self, 1693 candidate: Maybe<'ptr, $ty>, 1694 ) -> Option<bool> { 1695 assert_on_allowlist!( 1696 test_is_bit_valid_shared($ty): 1697 ManuallyDrop<UnsafeCell<()>>, 1698 ManuallyDrop<[UnsafeCell<u8>]>, 1699 ManuallyDrop<[UnsafeCell<bool>]>, 1700 CoreMaybeUninit<NotZerocopy>, 1701 CoreMaybeUninit<UnsafeCell<()>>, 1702 Wrapping<UnsafeCell<()>> 1703 ); 1704 1705 None 1706 } 1707 1708 #[allow(clippy::needless_lifetimes)] 1709 fn test_try_from_ref<'bytes>(&mut self, _bytes: &'bytes [u8]) -> Option<Option<&'bytes $ty>> { 1710 assert_on_allowlist!( 1711 test_try_from_ref($ty): 1712 ManuallyDrop<[UnsafeCell<bool>]> 1713 ); 1714 1715 None 1716 } 1717 1718 #[allow(clippy::needless_lifetimes)] 1719 fn test_try_from_mut<'bytes>(&mut self, _bytes: &'bytes mut [u8]) -> Option<Option<&'bytes mut $ty>> { 1720 assert_on_allowlist!( 1721 test_try_from_mut($ty): 1722 Option<Box<UnsafeCell<NotZerocopy>>>, 1723 Option<&'static UnsafeCell<NotZerocopy>>, 1724 Option<&'static mut UnsafeCell<NotZerocopy>>, 1725 Option<NonNull<UnsafeCell<NotZerocopy>>>, 1726 Option<fn()>, 1727 Option<FnManyArgs>, 1728 Option<extern "C" fn()>, 1729 Option<ECFnManyArgs>, 1730 *const NotZerocopy, 1731 *mut NotZerocopy 1732 ); 1733 1734 None 1735 } 1736 1737 fn test_try_read_from(&mut self, _bytes: &[u8]) -> Option<Option<&$ty>> { 1738 assert_on_allowlist!( 1739 test_try_read_from($ty): 1740 str, 1741 ManuallyDrop<[u8]>, 1742 ManuallyDrop<[bool]>, 1743 ManuallyDrop<[UnsafeCell<bool>]>, 1744 [u8], 1745 [bool] 1746 ); 1747 1748 None 1749 } 1750 1751 fn test_as_bytes(&mut self, _t: &ReadOnly<$ty>) -> Option<&[u8]> { 1752 assert_on_allowlist!( 1753 test_as_bytes($ty): 1754 Option<&'static UnsafeCell<NotZerocopy>>, 1755 Option<&'static mut UnsafeCell<NotZerocopy>>, 1756 Option<NonNull<UnsafeCell<NotZerocopy>>>, 1757 Option<Box<UnsafeCell<NotZerocopy>>>, 1758 Option<fn()>, 1759 Option<FnManyArgs>, 1760 Option<extern "C" fn()>, 1761 Option<ECFnManyArgs>, 1762 CoreMaybeUninit<u8>, 1763 CoreMaybeUninit<NotZerocopy>, 1764 CoreMaybeUninit<UnsafeCell<()>>, 1765 ManuallyDrop<UnsafeCell<()>>, 1766 ManuallyDrop<[UnsafeCell<u8>]>, 1767 ManuallyDrop<[UnsafeCell<bool>]>, 1768 Wrapping<UnsafeCell<()>>, 1769 *const NotZerocopy, 1770 *mut NotZerocopy 1771 ); 1772 1773 None 1774 } 1775 } 1776 1777 <$ty as TryFromBytesTestable>::with_passing_test_cases(|mut val| { 1778 // FIXME(#494): These tests only get exercised for types 1779 // which are `IntoBytes`. Once we implement #494, we should 1780 // be able to support non-`IntoBytes` types by zeroing 1781 // padding. 1782 1783 // We define `w` and `ww` since, in the case of the inherent 1784 // methods, Rust thinks they're both borrowed mutably at the 1785 // same time (given how we use them below). If we just 1786 // defined a single `w` and used it for multiple operations, 1787 // this would conflict. 1788 // 1789 // We `#[allow(unused_mut]` for the cases where the "real" 1790 // impls are used, which take `&self`. 1791 #[allow(unused_mut)] 1792 let (mut w, mut ww) = (AutorefWrapper::<$ty>(PhantomData), AutorefWrapper::<$ty>(PhantomData)); 1793 1794 let c = Ptr::from_ref(&*val); 1795 let c = c.forget_aligned(); 1796 // SAFETY: FIXME(#899): This is unsound. `$ty` is not 1797 // necessarily `IntoBytes`, but that's the corner we've 1798 // backed ourselves into by using `Ptr::from_ref`. 1799 let c = unsafe { c.assume_initialized() }; 1800 let res = w.test_is_bit_valid_shared(c); 1801 if let Some(res) = res { 1802 assert!(res, "{}::is_bit_valid (shared `Ptr`): got false, expected true", stringify!($ty)); 1803 } 1804 1805 let c = Ptr::from_mut(&mut *val); 1806 let c = c.forget_aligned(); 1807 // SAFETY: FIXME(#899): This is unsound. `$ty` is not 1808 // necessarily `IntoBytes`, but that's the corner we've 1809 // backed ourselves into by using `Ptr::from_ref`. 1810 let mut c = unsafe { c.assume_initialized() }; 1811 let res = <$ty as TryFromBytes>::is_bit_valid(c.reborrow_shared()); 1812 assert!(res, "{}::is_bit_valid (exclusive `Ptr`): got false, expected true", stringify!($ty)); 1813 1814 // `bytes` is `Some(val.as_bytes())` if `$ty: IntoBytes + 1815 // Immutable` and `None` otherwise. 1816 let bytes = w.test_as_bytes(&*val); 1817 1818 // The inner closure returns 1819 // `Some($ty::try_ref_from_bytes(bytes))` if `$ty: 1820 // Immutable` and `None` otherwise. 1821 let res = bytes.and_then(|bytes| ww.test_try_from_ref(bytes)); 1822 if let Some(res) = res { 1823 assert!(res.is_some(), "{}::try_ref_from_bytes: got `None`, expected `Some`", stringify!($ty)); 1824 } 1825 1826 if let Some(bytes) = bytes { 1827 // We need to get a mutable byte slice, and so we clone 1828 // into a `Vec`. However, we also need these bytes to 1829 // satisfy `$ty`'s alignment requirement, which isn't 1830 // guaranteed for `Vec<u8>`. In order to get around 1831 // this, we create a `Vec` which is twice as long as we 1832 // need. There is guaranteed to be an aligned byte range 1833 // of size `size_of_val(val)` within that range. 1834 let val = &*val; 1835 let size = mem::size_of_val(val); 1836 let align = mem::align_of_val(val); 1837 1838 let mut vec = bytes.to_vec(); 1839 vec.extend(bytes); 1840 let slc = vec.as_slice(); 1841 let offset = slc.as_ptr().align_offset(align); 1842 let bytes_mut = &mut vec.as_mut_slice()[offset..offset+size]; 1843 bytes_mut.copy_from_slice(bytes); 1844 1845 let res = ww.test_try_from_mut(bytes_mut); 1846 if let Some(res) = res { 1847 assert!(res.is_some(), "{}::try_mut_from_bytes: got `None`, expected `Some`", stringify!($ty)); 1848 } 1849 } 1850 1851 let res = bytes.and_then(|bytes| ww.test_try_read_from(bytes)); 1852 if let Some(res) = res { 1853 assert!(res.is_some(), "{}::try_read_from_bytes: got `None`, expected `Some`", stringify!($ty)); 1854 } 1855 }); 1856 #[allow(clippy::as_conversions)] 1857 <$ty as TryFromBytesTestable>::with_failing_test_cases(|c| { 1858 #[allow(unused_mut)] // For cases where the "real" impls are used, which take `&self`. 1859 let mut w = AutorefWrapper::<$ty>(PhantomData); 1860 1861 // This is `Some($ty::try_ref_from_bytes(c))` if `$ty: 1862 // Immutable` and `None` otherwise. 1863 let res = w.test_try_from_ref(c); 1864 if let Some(res) = res { 1865 assert!(res.is_none(), "{}::try_ref_from_bytes({:?}): got Some, expected None", stringify!($ty), c); 1866 } 1867 1868 let res = w.test_try_from_mut(c); 1869 if let Some(res) = res { 1870 assert!(res.is_none(), "{}::try_mut_from_bytes({:?}): got Some, expected None", stringify!($ty), c); 1871 } 1872 1873 1874 let res = w.test_try_read_from(c); 1875 if let Some(res) = res { 1876 assert!(res.is_none(), "{}::try_read_from_bytes({:?}): got Some, expected None", stringify!($ty), c); 1877 } 1878 }); 1879 1880 #[allow(dead_code)] 1881 const _: () = { static_assertions::assert_impl_all!($ty: TryFromBytes); }; 1882 }; 1883 ($ty:ty: $trait:ident) => { 1884 #[allow(dead_code)] 1885 const _: () = { static_assertions::assert_impl_all!($ty: $trait); }; 1886 }; 1887 ($ty:ty: !$trait:ident) => { 1888 #[allow(dead_code)] 1889 const _: () = { static_assertions::assert_not_impl_any!($ty: $trait); }; 1890 }; 1891 ($ty:ty: $($trait:ident),* $(,)? $(!$negative_trait:ident),*) => { 1892 $( 1893 assert_impls!($ty: $trait); 1894 )* 1895 1896 $( 1897 assert_impls!($ty: !$negative_trait); 1898 )* 1899 }; 1900 } 1901 1902 // NOTE: The negative impl assertions here are not necessarily 1903 // prescriptive. They merely serve as change detectors to make sure 1904 // we're aware of what trait impls are getting added with a given 1905 // change. Of course, some impls would be invalid (e.g., `bool: 1906 // FromBytes`), and so this change detection is very important. 1907 1908 assert_impls!( 1909 (): KnownLayout, 1910 Immutable, 1911 TryFromBytes, 1912 FromZeros, 1913 FromBytes, 1914 IntoBytes, 1915 Unaligned 1916 ); 1917 assert_impls!( 1918 u8: KnownLayout, 1919 Immutable, 1920 TryFromBytes, 1921 FromZeros, 1922 FromBytes, 1923 IntoBytes, 1924 Unaligned 1925 ); 1926 assert_impls!( 1927 i8: KnownLayout, 1928 Immutable, 1929 TryFromBytes, 1930 FromZeros, 1931 FromBytes, 1932 IntoBytes, 1933 Unaligned 1934 ); 1935 assert_impls!( 1936 u16: KnownLayout, 1937 Immutable, 1938 TryFromBytes, 1939 FromZeros, 1940 FromBytes, 1941 IntoBytes, 1942 !Unaligned 1943 ); 1944 assert_impls!( 1945 i16: KnownLayout, 1946 Immutable, 1947 TryFromBytes, 1948 FromZeros, 1949 FromBytes, 1950 IntoBytes, 1951 !Unaligned 1952 ); 1953 assert_impls!( 1954 u32: KnownLayout, 1955 Immutable, 1956 TryFromBytes, 1957 FromZeros, 1958 FromBytes, 1959 IntoBytes, 1960 !Unaligned 1961 ); 1962 assert_impls!( 1963 i32: KnownLayout, 1964 Immutable, 1965 TryFromBytes, 1966 FromZeros, 1967 FromBytes, 1968 IntoBytes, 1969 !Unaligned 1970 ); 1971 assert_impls!( 1972 u64: KnownLayout, 1973 Immutable, 1974 TryFromBytes, 1975 FromZeros, 1976 FromBytes, 1977 IntoBytes, 1978 !Unaligned 1979 ); 1980 assert_impls!( 1981 i64: KnownLayout, 1982 Immutable, 1983 TryFromBytes, 1984 FromZeros, 1985 FromBytes, 1986 IntoBytes, 1987 !Unaligned 1988 ); 1989 assert_impls!( 1990 u128: KnownLayout, 1991 Immutable, 1992 TryFromBytes, 1993 FromZeros, 1994 FromBytes, 1995 IntoBytes, 1996 !Unaligned 1997 ); 1998 assert_impls!( 1999 i128: KnownLayout, 2000 Immutable, 2001 TryFromBytes, 2002 FromZeros, 2003 FromBytes, 2004 IntoBytes, 2005 !Unaligned 2006 ); 2007 assert_impls!( 2008 usize: KnownLayout, 2009 Immutable, 2010 TryFromBytes, 2011 FromZeros, 2012 FromBytes, 2013 IntoBytes, 2014 !Unaligned 2015 ); 2016 assert_impls!( 2017 isize: KnownLayout, 2018 Immutable, 2019 TryFromBytes, 2020 FromZeros, 2021 FromBytes, 2022 IntoBytes, 2023 !Unaligned 2024 ); 2025 #[cfg(feature = "float-nightly")] 2026 assert_impls!( 2027 f16: KnownLayout, 2028 Immutable, 2029 TryFromBytes, 2030 FromZeros, 2031 FromBytes, 2032 IntoBytes, 2033 !Unaligned 2034 ); 2035 assert_impls!( 2036 f32: KnownLayout, 2037 Immutable, 2038 TryFromBytes, 2039 FromZeros, 2040 FromBytes, 2041 IntoBytes, 2042 !Unaligned 2043 ); 2044 assert_impls!( 2045 f64: KnownLayout, 2046 Immutable, 2047 TryFromBytes, 2048 FromZeros, 2049 FromBytes, 2050 IntoBytes, 2051 !Unaligned 2052 ); 2053 #[cfg(feature = "float-nightly")] 2054 assert_impls!( 2055 f128: KnownLayout, 2056 Immutable, 2057 TryFromBytes, 2058 FromZeros, 2059 FromBytes, 2060 IntoBytes, 2061 !Unaligned 2062 ); 2063 assert_impls!( 2064 bool: KnownLayout, 2065 Immutable, 2066 TryFromBytes, 2067 FromZeros, 2068 IntoBytes, 2069 Unaligned, 2070 !FromBytes 2071 ); 2072 assert_impls!( 2073 char: KnownLayout, 2074 Immutable, 2075 TryFromBytes, 2076 FromZeros, 2077 IntoBytes, 2078 !FromBytes, 2079 !Unaligned 2080 ); 2081 assert_impls!( 2082 str: KnownLayout, 2083 Immutable, 2084 TryFromBytes, 2085 FromZeros, 2086 IntoBytes, 2087 Unaligned, 2088 !FromBytes 2089 ); 2090 2091 assert_impls!( 2092 NonZeroU8: KnownLayout, 2093 Immutable, 2094 TryFromBytes, 2095 IntoBytes, 2096 Unaligned, 2097 !FromZeros, 2098 !FromBytes 2099 ); 2100 assert_impls!( 2101 NonZeroI8: KnownLayout, 2102 Immutable, 2103 TryFromBytes, 2104 IntoBytes, 2105 Unaligned, 2106 !FromZeros, 2107 !FromBytes 2108 ); 2109 assert_impls!( 2110 NonZeroU16: KnownLayout, 2111 Immutable, 2112 TryFromBytes, 2113 IntoBytes, 2114 !FromBytes, 2115 !Unaligned 2116 ); 2117 assert_impls!( 2118 NonZeroI16: KnownLayout, 2119 Immutable, 2120 TryFromBytes, 2121 IntoBytes, 2122 !FromBytes, 2123 !Unaligned 2124 ); 2125 assert_impls!( 2126 NonZeroU32: KnownLayout, 2127 Immutable, 2128 TryFromBytes, 2129 IntoBytes, 2130 !FromBytes, 2131 !Unaligned 2132 ); 2133 assert_impls!( 2134 NonZeroI32: KnownLayout, 2135 Immutable, 2136 TryFromBytes, 2137 IntoBytes, 2138 !FromBytes, 2139 !Unaligned 2140 ); 2141 assert_impls!( 2142 NonZeroU64: KnownLayout, 2143 Immutable, 2144 TryFromBytes, 2145 IntoBytes, 2146 !FromBytes, 2147 !Unaligned 2148 ); 2149 assert_impls!( 2150 NonZeroI64: KnownLayout, 2151 Immutable, 2152 TryFromBytes, 2153 IntoBytes, 2154 !FromBytes, 2155 !Unaligned 2156 ); 2157 assert_impls!( 2158 NonZeroU128: KnownLayout, 2159 Immutable, 2160 TryFromBytes, 2161 IntoBytes, 2162 !FromBytes, 2163 !Unaligned 2164 ); 2165 assert_impls!( 2166 NonZeroI128: KnownLayout, 2167 Immutable, 2168 TryFromBytes, 2169 IntoBytes, 2170 !FromBytes, 2171 !Unaligned 2172 ); 2173 assert_impls!( 2174 NonZeroUsize: KnownLayout, 2175 Immutable, 2176 TryFromBytes, 2177 IntoBytes, 2178 !FromBytes, 2179 !Unaligned 2180 ); 2181 assert_impls!( 2182 NonZeroIsize: KnownLayout, 2183 Immutable, 2184 TryFromBytes, 2185 IntoBytes, 2186 !FromBytes, 2187 !Unaligned 2188 ); 2189 2190 assert_impls!(Option<NonZeroU8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2191 assert_impls!(Option<NonZeroI8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2192 assert_impls!(Option<NonZeroU16>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2193 assert_impls!(Option<NonZeroI16>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2194 assert_impls!(Option<NonZeroU32>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2195 assert_impls!(Option<NonZeroI32>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2196 assert_impls!(Option<NonZeroU64>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2197 assert_impls!(Option<NonZeroI64>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2198 assert_impls!(Option<NonZeroU128>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2199 assert_impls!(Option<NonZeroI128>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2200 assert_impls!(Option<NonZeroUsize>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2201 assert_impls!(Option<NonZeroIsize>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); 2202 2203 // Implements none of the ZC traits. 2204 struct NotZerocopy; 2205 2206 #[rustfmt::skip] 2207 type FnManyArgs = fn( 2208 NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, 2209 ) -> (NotZerocopy, NotZerocopy); 2210 2211 // Allowed, because we're not actually using this type for FFI. 2212 #[allow(improper_ctypes_definitions)] 2213 #[rustfmt::skip] 2214 type ECFnManyArgs = extern "C" fn( 2215 NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, 2216 ) -> (NotZerocopy, NotZerocopy); 2217 2218 #[cfg(feature = "alloc")] 2219 assert_impls!(Option<Box<UnsafeCell<NotZerocopy>>>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2220 assert_impls!(Option<Box<[UnsafeCell<NotZerocopy>]>>: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2221 assert_impls!(Option<&'static UnsafeCell<NotZerocopy>>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2222 assert_impls!(Option<&'static [UnsafeCell<NotZerocopy>]>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2223 assert_impls!(Option<&'static mut UnsafeCell<NotZerocopy>>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2224 assert_impls!(Option<&'static mut [UnsafeCell<NotZerocopy>]>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2225 assert_impls!(Option<NonNull<UnsafeCell<NotZerocopy>>>: KnownLayout, TryFromBytes, FromZeros, Immutable, !FromBytes, !IntoBytes, !Unaligned); 2226 assert_impls!(Option<NonNull<[UnsafeCell<NotZerocopy>]>>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2227 assert_impls!(Option<fn()>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2228 assert_impls!(Option<FnManyArgs>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2229 assert_impls!(Option<extern "C" fn()>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2230 assert_impls!(Option<ECFnManyArgs>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2231 2232 assert_impls!(PhantomData<NotZerocopy>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2233 assert_impls!(PhantomData<UnsafeCell<()>>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2234 assert_impls!(PhantomData<[u8]>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2235 2236 assert_impls!(ManuallyDrop<u8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2237 // This test is important because it allows us to test our hand-rolled 2238 // implementation of `<ManuallyDrop<T> as TryFromBytes>::is_bit_valid`. 2239 assert_impls!(ManuallyDrop<bool>: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); 2240 assert_impls!(ManuallyDrop<[u8]>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2241 // This test is important because it allows us to test our hand-rolled 2242 // implementation of `<ManuallyDrop<T> as TryFromBytes>::is_bit_valid`. 2243 assert_impls!(ManuallyDrop<[bool]>: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); 2244 assert_impls!(ManuallyDrop<NotZerocopy>: !Immutable, !TryFromBytes, !KnownLayout, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2245 assert_impls!(ManuallyDrop<[NotZerocopy]>: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2246 assert_impls!(ManuallyDrop<UnsafeCell<()>>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); 2247 assert_impls!(ManuallyDrop<[UnsafeCell<u8>]>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); 2248 assert_impls!(ManuallyDrop<[UnsafeCell<bool>]>: KnownLayout, TryFromBytes, FromZeros, IntoBytes, Unaligned, !Immutable, !FromBytes); 2249 2250 assert_impls!(CoreMaybeUninit<u8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, Unaligned, !IntoBytes); 2251 assert_impls!(CoreMaybeUninit<NotZerocopy>: KnownLayout, TryFromBytes, FromZeros, FromBytes, !Immutable, !IntoBytes, !Unaligned); 2252 assert_impls!(CoreMaybeUninit<UnsafeCell<()>>: KnownLayout, TryFromBytes, FromZeros, FromBytes, Unaligned, !Immutable, !IntoBytes); 2253 2254 assert_impls!(Wrapping<u8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2255 // This test is important because it allows us to test our hand-rolled 2256 // implementation of `<Wrapping<T> as TryFromBytes>::is_bit_valid`. 2257 assert_impls!(Wrapping<bool>: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); 2258 assert_impls!(Wrapping<NotZerocopy>: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2259 assert_impls!(Wrapping<UnsafeCell<()>>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); 2260 2261 assert_impls!(Unalign<u8>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); 2262 // This test is important because it allows us to test our hand-rolled 2263 // implementation of `<Unalign<T> as TryFromBytes>::is_bit_valid`. 2264 assert_impls!(Unalign<bool>: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); 2265 assert_impls!(Unalign<NotZerocopy>: KnownLayout, Unaligned, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes); 2266 2267 assert_impls!( 2268 [u8]: KnownLayout, 2269 Immutable, 2270 TryFromBytes, 2271 FromZeros, 2272 FromBytes, 2273 IntoBytes, 2274 Unaligned 2275 ); 2276 assert_impls!( 2277 [bool]: KnownLayout, 2278 Immutable, 2279 TryFromBytes, 2280 FromZeros, 2281 IntoBytes, 2282 Unaligned, 2283 !FromBytes 2284 ); 2285 assert_impls!([NotZerocopy]: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2286 assert_impls!( 2287 [u8; 0]: KnownLayout, 2288 Immutable, 2289 TryFromBytes, 2290 FromZeros, 2291 FromBytes, 2292 IntoBytes, 2293 Unaligned, 2294 ); 2295 assert_impls!( 2296 [NotZerocopy; 0]: KnownLayout, 2297 !Immutable, 2298 !TryFromBytes, 2299 !FromZeros, 2300 !FromBytes, 2301 !IntoBytes, 2302 !Unaligned 2303 ); 2304 assert_impls!( 2305 [u8; 1]: KnownLayout, 2306 Immutable, 2307 TryFromBytes, 2308 FromZeros, 2309 FromBytes, 2310 IntoBytes, 2311 Unaligned, 2312 ); 2313 assert_impls!( 2314 [NotZerocopy; 1]: KnownLayout, 2315 !Immutable, 2316 !TryFromBytes, 2317 !FromZeros, 2318 !FromBytes, 2319 !IntoBytes, 2320 !Unaligned 2321 ); 2322 2323 assert_impls!(*const NotZerocopy: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2324 assert_impls!(*mut NotZerocopy: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2325 assert_impls!(*const [NotZerocopy]: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2326 assert_impls!(*mut [NotZerocopy]: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2327 assert_impls!(*const dyn Debug: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2328 assert_impls!(*mut dyn Debug: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); 2329 2330 #[cfg(feature = "simd")] 2331 { 2332 #[allow(unused_macros)] 2333 macro_rules! test_simd_arch_mod { 2334 ($arch:ident, $($typ:ident),*) => { 2335 { 2336 use core::arch::$arch::{$($typ),*}; 2337 use crate::*; 2338 $( assert_impls!($typ: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); )* 2339 } 2340 }; 2341 } 2342 #[cfg(target_arch = "x86")] 2343 test_simd_arch_mod!(x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i); 2344 2345 #[cfg(all(not(no_zerocopy_simd_x86_avx12_1_89_0), target_arch = "x86"))] 2346 test_simd_arch_mod!(x86, __m512bh, __m512, __m512d, __m512i); 2347 2348 #[cfg(target_arch = "x86_64")] 2349 test_simd_arch_mod!(x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i); 2350 2351 #[cfg(all(not(no_zerocopy_simd_x86_avx12_1_89_0), target_arch = "x86_64"))] 2352 test_simd_arch_mod!(x86_64, __m512bh, __m512, __m512d, __m512i); 2353 2354 #[cfg(target_arch = "wasm32")] 2355 test_simd_arch_mod!(wasm32, v128); 2356 2357 #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))] 2358 test_simd_arch_mod!( 2359 powerpc, 2360 vector_bool_long, 2361 vector_double, 2362 vector_signed_long, 2363 vector_unsigned_long 2364 ); 2365 2366 #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))] 2367 test_simd_arch_mod!( 2368 powerpc64, 2369 vector_bool_long, 2370 vector_double, 2371 vector_signed_long, 2372 vector_unsigned_long 2373 ); 2374 #[cfg(all(target_arch = "aarch64", not(no_zerocopy_aarch64_simd_1_59_0)))] 2375 #[rustfmt::skip] 2376 test_simd_arch_mod!( 2377 aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t, 2378 int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t, 2379 int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, 2380 poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t, 2381 poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t, 2382 uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x4x2_t, uint16x4x3_t, 2383 uint16x4x4_t, uint16x8_t, uint32x2_t, uint32x4_t, uint64x1_t, uint64x2_t 2384 ); 2385 } 2386 } 2387 } 2388