Not quite, even the "correct" repr(C)
(using actual platform layout) would actually be deterministic and allow reinterpreting values. It'd just be a different algorithm than it is today. But you already replied to that above, I think.
The actual conflict is with this paragraph:
For each field in declaration order in the struct, first determine the size and alignment of the field. If the current offset is not a multiple of the fieldās alignment, then add padding bytes to the current offset until it is a multiple of the fieldās alignment. The offset for the field is what the current offset is now. Then increase the current offset by the size of the field.
Unless we want to somehow argue that "alignment" here refers to something different from align_of
, this indeed does conflict with the goal of being "interoperable with the C Language". The source of most of these bugs is that young Rust was a bit naive about there being only one notion of "alignment" that we could use everywhere, when in fact there are at least two (well, three, if you also count the "preferred" alignment, but that seems less problematic).
So yeah, it is a decision between the permanent wart of "the layout that matches the C
layout is not called C
", and breaking this promise that has been in the type layout section since 7 years.
In terms of tier 1 and tier 2 targets, the breakage based on what I have seen so far would be limited to certain types on MSVC:
(It'd also affect many more types on 32bit MSVC if we want to use this to fix this by setting the align_of
of u64
to 4... but we already decided not to do that and it is unclear if it's worth revising that decision.)
The last one can be fairly easily linted against. And I think the other two could also be detected with a lint as long as the lint runs during monomorphization, where we can see through all the generics. So this is not insurmountable:
- add a
repr(linear)
that follows the rules quoted above
- add a lint for the problematic types suggesting to use
repr(linear)
- now warning-free code can change its edition without changing behavior
Well... almost. During monomorphization a type is a mix of many editions, and the crate that declares the repr(C)
type might not be the place where the warning about changing behavior actually occurs.