Open ds84182 opened 3 weeks ago
An asserting const within a trait impl will trigger a late-monomorphization error. This can be used to directly check for uninit bytes.
This should be opt-in in the derive trait. For manual implementations a helper macro could provide the same field checks.
Please note that this implementation is was written in a couple of minutes, so it may have unforeseen issues.
Example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8d97b800a96d2becd5d7b75fa52fb3fe
unsafe trait NoUninit { // Asserts fields are aligned, returns alignment const FIELDS_ALIGNED: usize; } unsafe impl NoUninit for u8 { const FIELDS_ALIGNED: usize = std::mem::align_of::<Self>(); } unsafe impl NoUninit for u16 { const FIELDS_ALIGNED: usize = std::mem::align_of::<Self>(); } unsafe impl<const N: usize, T: NoUninit> NoUninit for [T; N] { const FIELDS_ALIGNED: usize = <T as NoUninit>::FIELDS_ALIGNED; } #[repr(C)] struct MaybeNoUninit<T> { byte: u8, payload: T, } unsafe impl<T: NoUninit> NoUninit for MaybeNoUninit<T> { const FIELDS_ALIGNED: usize = { let mut offset = 0; let field_align = <u8 as NoUninit>::FIELDS_ALIGNED; offset += std::mem::size_of::<u8>(); offset = (offset + (field_align - 1)) & !(field_align - 1); let field_align = <T as NoUninit>::FIELDS_ALIGNED; assert!((offset & (field_align - 1)) == 0, "`payload` is misaligned, `byte` has a smaller alignment"); offset += std::mem::size_of::<u8>(); offset = (offset + (field_align - 1)) & !(field_align - 1); let struct_align = std::mem::align_of::<T>(); assert!((offset & (struct_align - 1)) == 0, "struct has trailing padding bytes"); struct_align }; } fn main() { // These are fine: let _ = <MaybeNoUninit<u8> as NoUninit>::FIELDS_ALIGNED; let _ = <MaybeNoUninit<[u8; 2]> as NoUninit>::FIELDS_ALIGNED; let _ = <MaybeNoUninit<[[u8; 2]; 8]> as NoUninit>::FIELDS_ALIGNED; // Causes late-mono error: let _ = <MaybeNoUninit<u16> as NoUninit>::FIELDS_ALIGNED; }
An asserting const within a trait impl will trigger a late-monomorphization error. This can be used to directly check for uninit bytes.
This should be opt-in in the derive trait. For manual implementations a helper macro could provide the same field checks.
Please note that this implementation is was written in a couple of minutes, so it may have unforeseen issues.
Example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8d97b800a96d2becd5d7b75fa52fb3fe