You should provide a trait and custom derive to enforce the things you want.
unsafe trait FlatData {}
unsafe impl FlatData for u8 {}
// ...
#[derive(FlatData)]
#[repr(C)]
struct Dre {
a: A,
b: B,
/* ... */
}
// if the struct has repr(C), expands to:
const IMPL_FLATDATA_FOR_Dre: () = {
fn assert_flatdata<T: FlatData>() {}
fn compile_time_checks() {
assert_flatdata::<A>(); // does not compile if one of the field types is bad
assert_flatdata::<B>();
/* ... */
}
unsafe impl FlatData for Dre {}
}