vasi/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
#![no_std]
// https://github.com/rust-lang/rfcs/blob/master/text/2585-unsafe-block-in-unsafe-fn.md
#![deny(unsafe_op_in_unsafe_fn)]
// For use by code generated by vasi_macro::VirtualAddressSpaceIndependent;
#[doc(hidden)]
pub use static_assertions::assert_impl_all;
pub use vasi_macro::VirtualAddressSpaceIndependent;
/// A type implementing this trait guarantees that accessing instances
/// of that type outside of their original virtual address space does not
/// violate Rust's safety requirements.
///
/// This is mostly equivalent to them being *self-contained*: not referring to
/// memory outside of the range `[&self, &self + std::mem::sizeof<T>()]`.
/// However, they *may* reference memory outside of that range if they somehow
/// ensure that they only do so from inside the virtual address space where it
/// is valid to do so.
///
/// Types implementing this trait can definitely not contain references. If
/// they contain pointers, the type is responsible for ensuring those pointers
/// aren't dereferenced outside a virtual address space where they are valid.
///
/// *Relative* pointers, e.g. as implemented in
/// [rkyv](https://crates.io/crates/rkyv), are acceptable as long as they point
/// within the boundaries of the enclosing type.
///
/// The type must also be FFI-safe; e.g. have a stable layout (e.g. `[repr(C)]`),
/// to help ensure that different processes accessing data of a given type
/// actually agree on its layout. Note though that is necessary, but not
/// sufficient, to ensure they agree on the layout; e.g. things can still go
/// wrong if processes use different versions of the type. (TODO: maybe split
/// this property into a separate trait).
///
/// # Safety
///
/// The type must actually be self-contained, as above.
pub unsafe trait VirtualAddressSpaceIndependent {
/// Used by the derive macro to validate that fields are Vasi.
const IGNORE: () = ();
}
// Types not containing any pointers are trivially VirtualAddressSpaceIndependent.
unsafe impl VirtualAddressSpaceIndependent for i64 {}
unsafe impl VirtualAddressSpaceIndependent for u64 {}
unsafe impl VirtualAddressSpaceIndependent for i32 {}
unsafe impl VirtualAddressSpaceIndependent for u32 {}
unsafe impl VirtualAddressSpaceIndependent for i16 {}
unsafe impl VirtualAddressSpaceIndependent for u16 {}
unsafe impl VirtualAddressSpaceIndependent for i8 {}
unsafe impl VirtualAddressSpaceIndependent for u8 {}
unsafe impl VirtualAddressSpaceIndependent for usize {}
unsafe impl VirtualAddressSpaceIndependent for isize {}
unsafe impl VirtualAddressSpaceIndependent for bool {}
// e.g. "This type has the same in-memory representation as the underlying integer type, u64"
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU64 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI64 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU32 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI32 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU16 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI16 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU8 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI8 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicBool {}
// An array of T is [VirtualAddressSpaceIndependent] if its elements are.
unsafe impl<T, const N: usize> VirtualAddressSpaceIndependent for [T; N] where
T: VirtualAddressSpaceIndependent
{
}
// PhantomData is intrinsically VirtualAddressSpaceIndependent.
//
// Conservatively only implement when T is VirtualAddressSpaceIndependent,
// but unclear whether this restriction is necessary.
unsafe impl<T> VirtualAddressSpaceIndependent for core::marker::PhantomData<T> where
T: VirtualAddressSpaceIndependent
{
}
// Cell is `repr(transparent)` around an `UnsafeCell<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::cell::Cell<T> where
T: VirtualAddressSpaceIndependent
{
}
// UnsafeCell is `repr(transparent)` around a `T`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::cell::UnsafeCell<T> where
T: VirtualAddressSpaceIndependent
{
}
// ManuallyDrop is `repr(transparent)` around a `<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::mem::ManuallyDrop<T> where
T: VirtualAddressSpaceIndependent
{
}
// MaybeUninit is `repr(transparent)` around a union of `()` and `ManuallyDrop<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::mem::MaybeUninit<T> where
T: VirtualAddressSpaceIndependent
{
}
unsafe impl VirtualAddressSpaceIndependent for () {}