@@ -199,19 +199,40 @@ mod zerocopy {
199
199
///
200
200
/// # Safety
201
201
///
202
- /// If `T: FromZeroes`, then unsafe code may assume that it is sound to treat
203
- /// any initialized sequence of zero bytes of length `size_of::<T>()` as a `T`.
202
+ /// *This section describes what is required in order for `T: FromZeroes`, and
203
+ /// what unsafe code may assume of such types. `#[derive(FromZeroes)]` only
204
+ /// permits types which satisfy these requirements. If you don't plan on
205
+ /// implementing `FromZeroes` manually, and you don't plan on writing unsafe
206
+ /// code that operates on `FromZeroes` types, then you don't need to read this
207
+ /// section.*
208
+ ///
209
+ /// If `T: FromZeroes`, then unsafe code may assume that:
210
+ /// - It is sound to treat any initialized sequence of zero bytes of length
211
+ /// `size_of::<T>()` as a `T`.
212
+ /// - Given `b: &[u8]` where `b.len() == size_of::<T>()`, `b` is aligned to
213
+ /// `align_of::<T>()`, and `b` contains only zero bytes, it is sound to
214
+ /// construct a `t: &T` at the same address as `b`, and it is sound for both
215
+ /// `b` and `t` to be live at the same time.
216
+ ///
204
217
/// If a type is marked as `FromZeroes` which violates this contract, it may
205
218
/// cause undefined behavior.
206
219
///
207
- /// If a type has the following properties, then it is safe to implement
220
+ /// If a type has the following properties, then it is sound to implement
208
221
/// `FromZeroes` for that type:
209
- /// - If the type is a struct, all of its fields must implement `FromZeroes`
222
+ /// - If the type is a struct, all of its fields must satisfy the requirements
223
+ /// to be `FromZeroes` (they do not actually have to be `FromZeroes`).
210
224
/// - If the type is an enum, it must be C-like (meaning that all variants have
211
- /// no fields) and it must have a variant with a discriminant of `0` (see [the
212
- /// reference] for a description of how discriminant values are chosen)
225
+ /// no fields) and it must have a variant with a discriminant of `0`. See [the
226
+ /// reference] for a description of how discriminant values are chosen.
227
+ /// - The type must not contain any [`UnsafeCell`]s (this is required in order
228
+ /// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
229
+ /// memory). The type may contain references or pointers to `UnsafeCell`s so
230
+ /// long as those values can themselves be initialized from zeroes
231
+ /// (`FromZeroes` is not currently implemented for, e.g.,
232
+ /// `Option<&UnsafeCell<_>>`, but it could be one day).
213
233
///
214
234
/// [the reference]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
235
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
215
236
///
216
237
/// # Rationale
217
238
///
@@ -420,22 +441,40 @@ pub unsafe trait FromZeroes {
420
441
///
421
442
/// # Safety
422
443
///
423
- /// If `T: FromBytes`, then unsafe code may assume that it is sound to treat any
424
- /// initialized sequence of bytes of length `size_of::<T>()` as a `T`. If a type
425
- /// is marked as `FromBytes` which violates this contract, it may cause
426
- /// undefined behavior.
444
+ /// *This section describes what is required in order for `T: FromBytes`, and
445
+ /// what unsafe code may assume of such types. `#[derive(FromBytes)]` only
446
+ /// permits types which satisfy these requirements. If you don't plan on
447
+ /// implementing `FromBytes` manually, and you don't plan on writing unsafe code
448
+ /// that operates on `FromBytes` types, then you don't need to read this
449
+ /// section.*
450
+ ///
451
+ /// If `T: FromBytes`, then unsafe code may assume that:
452
+ /// - It is sound to treat any initialized sequence of bytes of length
453
+ /// `size_of::<T>()` as a `T`.
454
+ /// - Given `b: &[u8]` where `b.len() == size_of::<T>()` and `b` is aligned to
455
+ /// `align_of::<T>()`, it is sound to construct a `t: &T` at the same address
456
+ /// as `b`, and it is sound for both `b` and `t` to be live at the same time.
457
+ ///
458
+ /// If a type is marked as `FromBytes` which violates this contract, it may
459
+ /// cause undefined behavior.
427
460
///
428
- /// If a type has the following properties, then it is safe to implement
461
+ /// If a type has the following properties, then it is sound to implement
429
462
/// `FromBytes` for that type:
430
- /// - If the type is a struct, all of its fields must implement `FromBytes`
463
+ /// - If the type is a struct, all of its fields must satisfy the requirements
464
+ /// to be `FromBytes` (they do not actually have to be `FromBytes`)
431
465
/// - If the type is an enum:
432
- /// - It must be a C-like enum (meaning that all variants have no fields)
466
+ /// - It must be a C-like enum (meaning that all variants have no fields).
433
467
/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
434
468
/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
435
469
/// - The maximum number of discriminants must be used (so that every possible
436
470
/// bit pattern is a valid one). Be very careful when using the `C`,
437
471
/// `usize`, or `isize` representations, as their size is
438
472
/// platform-dependent.
473
+ /// - The type must not contain any [`UnsafeCell`]s (this is required in order
474
+ /// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
475
+ /// memory).
476
+ ///
477
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
439
478
///
440
479
/// # Rationale
441
480
///
@@ -546,27 +585,43 @@ pub unsafe trait FromBytes: FromZeroes {
546
585
///
547
586
/// # Safety
548
587
///
549
- /// If `T: AsBytes`, then unsafe code may assume that it is sound to treat any
550
- /// instance of the type as an immutable `[u8]` of length `size_of::<T>()`. If a
551
- /// type is marked as `AsBytes` which violates this contract, it may cause
588
+ /// *This section describes what is required in order for `T: AsBytes`, and what
589
+ /// unsafe code may assume of such types. `#[derive(AsBytes)]` only permits
590
+ /// types which satisfy these requirements. If you don't plan on implementing
591
+ /// `AsBytes` manually, and you don't plan on writing unsafe code that operates
592
+ /// on `AsBytes` types, then you don't need to read this section.*
593
+ ///
594
+ /// If `T: AsBytes`, then unsafe code may assume that:
595
+ /// - It is sound to treat any `t: T` as an immutable `[u8]` of length
596
+ /// `size_of_val(t)`.
597
+ /// - Given `t: &T`, it is sound to construct a `b: &[u8]` where `b.len() ==
598
+ /// size_of_val(t)` at the same address as `t`, and it is sound for both `b`
599
+ /// and `t` to be live at the same time.
600
+ ///
601
+ /// If a type is marked as `AsBytes` which violates this contract, it may cause
552
602
/// undefined behavior.
553
603
///
554
- /// If a type has the following properties, then it is safe to implement
555
- /// `AsBytes` for that type
604
+ /// If a type has the following properties, then it is sound to implement
605
+ /// `AsBytes` for that type:
556
606
/// - If the type is a struct:
557
607
/// - It must have a defined representation (`repr(C)`, `repr(transparent)`,
558
608
/// or `repr(packed)`).
559
- /// - All of its fields must be `AsBytes`
609
+ /// - All of its fields must satisfy the requirements to be `AsBytes` (they do
610
+ /// not actually have to be `AsBytes`).
560
611
/// - Its layout must have no padding. This is always true for
561
612
/// `repr(transparent)` and `repr(packed)`. For `repr(C)`, see the layout
562
613
/// algorithm described in the [Rust Reference].
563
614
/// - If the type is an enum:
564
- /// - It must be a C-like enum (meaning that all variants have no fields)
615
+ /// - It must be a C-like enum (meaning that all variants have no fields).
565
616
/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
566
617
/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
618
+ /// - The type must not contain any [`UnsafeCell`]s (this is required in order
619
+ /// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
620
+ /// memory).
567
621
///
568
622
/// [type-layout]: https://doc.rust-lang.org/reference/type-layout.html
569
623
/// [Rust Reference]: https://doc.rust-lang.org/reference/type-layout.html
624
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
570
625
pub unsafe trait AsBytes {
571
626
// The `Self: Sized` bound makes it so that this function doesn't prevent
572
627
// `AsBytes` from being object safe. Note that other `AsBytes` methods
@@ -692,6 +747,13 @@ pub unsafe trait AsBytes {
692
747
///
693
748
/// # Safety
694
749
///
750
+ /// *This section describes what is required in order for `T: Unaligned`, and
751
+ /// what unsafe code may assume of such types. `#[derive(Unaligned)]` only
752
+ /// permits types which satisfy these requirements. If you don't plan on
753
+ /// implementing `Unaligned` manually, and you don't plan on writing unsafe code
754
+ /// that operates on `Unaligned` types, then you don't need to read this
755
+ /// section.*
756
+ ///
695
757
/// If `T: Unaligned`, then unsafe code may assume that it is sound to produce a
696
758
/// reference to `T` at any memory location regardless of alignment. If a type
697
759
/// is marked as `Unaligned` which violates this contract, it may cause
0 commit comments