# unsafe-fields Support for unsafe fields. This crate provides the `unsafe_fields!` macro, which can be used to mark fields as unsafe. Unsafe fields automatically have their types wrapped using the `Unsafe` wrapper type. An `Unsafe` is intended to be used to for struct, enum, or union fields which carry safety invariants. All accessors are `unsafe`, which requires any use of an `Unsafe` field to be inside an `unsafe` block. One exception is `Unsafe::as_ref`, which is available when the `zerocopy_0_8` feature is enabled. See its docs for more information. An unsafe field has the type `Unsafe`. `O` is the enclosing type (struct, enum, or union), `F` is the type of the field, and `NAME_HASH` is the hash of the field's name. `O` prevents swapping unsafe fields of the same `F` type between different enclosing types, and `NAME_HASH` prevents swapping different fields of the same `F` type within the same enclosing type. Note that swapping the same field between instances of the same type [cannot be prevented](crate#limitations). [immutable]: zerocopy_0_8::Immutable ## Examples ```rust use unsafe_fields::{unsafe_fields, Unsafe}; unsafe_fields! { /// A `usize` which is guaranteed to be even. pub struct EvenUsize { // INVARIANT: `n` is even. #[unsafe] n: usize, } } impl EvenUsize { /// Constructs a new `EvenUsize`. /// /// Returns `None` if `n` is odd. pub fn new(n: usize) -> Option { if n % 2 != 0 { return None; } // SAFETY: We just confirmed that `n` is even. let n = unsafe { Unsafe::new(n) }; Some(EvenUsize { n }) } } ``` Attempting to swap unsafe fields of the same type is prevented: ```rust,compile_fail,E0308 use unsafe_fields::{unsafe_fields, Unsafe}; unsafe_fields! { /// A range. pub struct Range { // INVARIANT: `lo <= hi`. #[unsafe] lo: usize, #[unsafe] hi: usize, } } impl Range { pub fn swap(&mut self) { // ERROR: Mismatched types core::mem::swap(&mut self.lo, &mut self.hi); } } ``` ## Limitations Note that we cannot prevent `Unsafe`s from being swapped between the same field in instances of the same type: ```rust use unsafe_fields::{unsafe_fields, Unsafe}; unsafe_fields! { /// A `usize` which is guaranteed to be even. pub struct EvenUsize { // INVARIANT: `n` is even. #[unsafe] n: usize, } } pub fn swap(a: &mut EvenUsize, b: &mut EvenUsize) { core::mem::swap(&mut a.n, &mut b.n); } ``` ## Disclaimer Disclaimer: This is not an officially supported Google product.