Repository navigation
Description
This is the summary issue for a bug fix related to repr(...) hints. The goal of this page is describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our breaking change policy guidelines.
What is the warning for?
The compiler incorrectly accepts #[repr(...)] hints on data types where the hints are incompatible and have conflicts. Examples of this includes:
// from `src/test/ui/conflicting-repr-hints.rs
#[repr(u32, u64)] //~ ERROR conflicting representation hints
enum D {
D,
}We are presently issuing a deny-by-default lint when conflicting representation hints are used together but we expect to transition the lint to hard errors in the future.
How can you fix your code?
Generally speaking, the conflict should be fixed by more clearly expressing your intent so that the conflict is resolved.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsIdea
Activity
Rollup merge of rust-lang#68586 - Centril:repr-deny, r=pnkfelix
Manishearth commentedon Jan 31, 2020
As discussed a bit in #68428 perhaps we should remove the warning and add semantics for
#[repr(C, Int)](namely, "fold intorepr(C)").C++ supports
enum class Foo: uint16_t, and we heavily recommend you only passrepr(C)types across FFI boundaries, so it makes sense that the correct thing to write for this is#[repr(C, u16)]. Furthermore, for dataful enums,#[repr(C, u16)]actually does work, and it's weird for this not to be consistent.Centril commentedon Feb 24, 2020
Beta crater results in #68586 (comment):
Based on these very limited results I don't think it's justified to retcon this into the specification, and making it an error again in the near future should be possible.
ecstatic-morse commentedon Feb 24, 2020
enum-utilshas a test that ensures#[repr(C, u16)]works. You shouldn't consider it when determining fallout.marmeladema commentedon Feb 18, 2021
Just encountered this error.
I wonder how does it relate to
Will that make both those RFC obsolete?
Also, will it be turned into a hard error in edition 2021?
Rollup merge of rust-lang#128727 - RalfJung:conflicting-repr-future-i…
Unrolled build for rust-lang#128727
[-]Tracking issue for conflicting `repr(...)` hints future compatibility[/-][+]Tracking issue for future-incompatibility lint `conflicting_repr_hints`[/+]Jeremiah-Griffin commentedon May 3, 2025
This lint presently errors if multiple of the same repr is applied to the same item as seen here:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=01dc845a8cec1b1e7f8d90445ad89b80
Supporting multiple identical reprs is useful when annotating the same item with multiple proc macros which themselves annotate a repr for the item. I feel this restriction should thus be loosened.
NUnitTester commentedon Jul 6, 2025
Currently, I get error that conflicting representations is not allowed, but it should not conflicting. Because I can also define the width representation of a enum (at least in C++).
Skgland commentedon Jul 11, 2025
This is allowed when the enum has at least one non-unit variant (even if the only non-unit variant doesn't have any fields).
Your example (after removing or filling in ...) compiles play-ground
Edit:
Note: RFC-2195
repr({integer})is allowed, butrepr(C, {integer})is notrepr({integer})andrepr(C, {integer})are allowed and behave differentlyeliminmax commentedon Dec 4, 2025
As of C23, C also allows specifying the backing type of its enums, with similar syntax to C++, so
#[repr(C, u8)]would seem to be the most logical annotation for a Rust version of a C enum like the following:kupiakos commentedon May 13, 2026
My proposal is that a field-less
repr(u16)enumbe defined as ABI-compatible with a C/C++ enum usinguint16_tas its fixed backing integer - noCrequired. This would mean thatrepr(C, Int)on a field-less enum would remain invalid (and not useful to spell).The issue I have with using
repr(C, u16)to indicate compatibility withenum Foo : uint16_tis becauseCon an enum with fields functions to change its layout and not just the ABI of the discriminant.repr(u16)is laid out as a union-of-structs, where the first field of each union is a discriminant enum, whilerepr(C, u16)is a struct with a discriminant enum field and a union data field.RFC 2195 states that this Rust enum:
can be correctly manipulated in C++ with this definition:
Because of this, Rust already supports interoperating with C/C++ enums using a fixed backing
Intwithout spellingrepr(C): but only when it's the discriminant field for an enum with fields. It would be consistent to extend this to field-less enums as well by defining ABI compatibility between field-less#[repr(Int)] enum fooandenum foo: CEquivalentOfInt/enum class foo : CppEquivalentOfIntwithout requiringrepr(C).I struggle to see serious downsides to making this promise: is there any optimization or sanitization that this would preclude?
If CFI becomes a higher priority to support, then I think this promise would be necessary to support existing codebases that interoperate with enums using a fixed backing integer.
eliminmax commentedon Jun 22, 2026
I would argue that for fieldless enums,
#[repr(C, Int)]and#[repr(Int)]should be equivalent, for the sake of the principle of least astonishment. I know when I was trying to define a fieldless enum for use in a project that used a mix of Rust and C23, and the compiler flagged it. I can't imagine any problems that would occur from treating them as equivalent, but I could very well be missing something.That said, It's a bit off-topic, but I noticed a significant problem with the C++ code quoted from RFC 2194 in the previous comment. I'm hiding it in a
<details>block to avoid cluttering this issue. If anyone involved in Rust development could direct me to a more appropriate place to discuss the issue, please let me know.Amateur language lawyering ahead
I am coming from an hobbyist C and Rust background, not C++, but as I understand, that is invalid in both C and C++, for different reasons.
For C, it's trivial: the
enum classdeclaration is not valid, as it has no concept of classes. The RFC text suggests just using the backing integer type, but, as of C23, simply omitting the wordclassshould make this valid in C, though adoption of new C versions is quite slow.As I understand it, C++ only allows the most recently-set union variant to be accessed, so even though the tag is at the same offset regardless of variant, it is undefined behavior to read it unless, by some miracle of statistics, it always happens to go through the correct variant.
Because splitting the tag and the payload into separate members of a struct could cause alignment issues, I don't believe there's any way to rewrite this to be valid, standards-compliant C++ for all possible
#[repr(C)]enums.