It always has, we lint for this, and the Rust struct layout has been officially left unspecified (making assumptions based on it UB) from before 1.0, anyway.
> One would think that would be 'repr("C")', since here, "C" is neither a reserved word nor a variable, but, whatever.
Neither is 'repr' - they're both just identifiers in an attribute. #[attr("string literal")] is newer and still unstable (as part of the new macro system).
The bit array packing is something we've wanted to do for a long while, but it requires an opt-in along the lines of "disallow taking references to any (sub-byte) fields".
#[repr(packed)] is the same as the C equivalent, be it attribute or pragma, in that it only removes alignment padding and does nothing to booleans.
Every micro controller I've ever worked with has header files defining bit fields for hardware registers. It's a matter of what level you're writing for. I would expect Linux to contain tons of these.
Pascal had "packed" as an option for structures and arrays. Using "packed array of boolean" got you a bit array. Rust has "repr(packed)", but it was broken as of Rust 1.0. Something that has no machine address, such as an individual bit, is apparently troublesome. C supports bit fields in structs, but that feature is seldom used.