Skip to content

Support repr(C) for rustified enums - #3265

Open
thedataking wants to merge 6 commits into
rust-lang:mainfrom
immunant:rustified-enum-repr-c
Open

Support repr(C) for rustified enums#3265
thedataking wants to merge 6 commits into
rust-lang:mainfrom
immunant:rustified-enum-repr-c

Conversation

@thedataking

@thedataking thedataking commented Aug 14, 2025

Copy link
Copy Markdown
Contributor

Adds a rustified enum style that uses repr(C) instead of a fixed integer
repr. Cross-language CFI requires this for enums passed across the FFI
boundary, since the Rust and C/C++ function types must agree
(https://rcvalle.com/docs/rust-cfi-design-doc/).

Rust's repr(C) does not match every C/C++ enum layout, e.g. with
-fshort-enums, an explicit underlying type, or values outside the c_int
range. bindgen now warns at generation time when the enum's layout is not
int-sized, the option docs call out the caveat, and layout tests are
emitted for repr(C) rustified enums so a mismatch fails to compile.

Closes #3263.

@thedataking
thedataking force-pushed the rustified-enum-repr-c branch from 33d5339 to 1885dc0 Compare August 14, 2025 07:39
thedataking pushed a commit to immunant/rust-bindgen that referenced this pull request Aug 15, 2025

@emilio emilio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! One nit

Comment thread bindgen/codegen/mod.rs Outdated

@emilio emilio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if we implement the suggested check for enum class Foo : uint8_t and so, we might not even need to add this switch? We could just repr(C) by default...

I think with this patch if you have something like:

enum class Foo : uint8_t {
};

Using this option will miscompile it.

At the very least we should add a big warning on this option since it'd cause wrong struct layout.

@thedataking

Copy link
Copy Markdown
Contributor Author

At the very least we should add a big warning on this option since it'd cause wrong struct layout.

I agree this would be good. However, it appears that LLVM does not expose the necessary APIs. Even if we exposed the necessary functionality, it would presumably only work for recent clang versions. Thoughts on how to proceed?

thedataking pushed a commit to immunant/rust-bindgen that referenced this pull request Aug 21, 2025
@thedataking
thedataking force-pushed the rustified-enum-repr-c branch from ec7b724 to d020ef1 Compare August 21, 2025 10:49
@emilio

emilio commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

What do you think of extending our layout tests to test the layout of enums? I think at least that would signal that there's something wrong with the generated code if you misuse this option.

Other than that it looks good.

@workingjubilee

Copy link
Copy Markdown
Member

Our repr(C) layout is actually very likely to be incorrect for many enums and we are considering how to deprecate it because it is very hard to address this.

@thedataking
thedataking force-pushed the rustified-enum-repr-c branch from d020ef1 to 61f39db Compare January 8, 2026 22:19
thedataking pushed a commit to immunant/rust-bindgen that referenced this pull request Jan 8, 2026
@workingjubilee

Copy link
Copy Markdown
Member

@thedataking Your added test doesn't touch the case of most concern for repr(C): enums with values bigger than the platform's c_int.

thedataking pushed a commit to immunant/rust-bindgen that referenced this pull request Jan 15, 2026
@thedataking
thedataking force-pushed the rustified-enum-repr-c branch 2 times, most recently from 867ed28 to a11cced Compare January 15, 2026 04:27
@thedataking

Copy link
Copy Markdown
Contributor Author

@thedataking Your added test doesn't touch the case of most concern for repr(C): enums with values bigger than the platform's c_int.

Good point, I added a test that requires the enum to have a 64-bit value. Any other cases of concern I should add?

@thedataking

Copy link
Copy Markdown
Contributor Author

What do you think of extending our layout tests to test the layout of enums? I think at least that would signal that there's something wrong with the generated code if you misuse this option.

@emilio I've added test cases for repr(C) specifically. I can also add testcases for rustified enums more broadly but that is a larger change... do you want it to be part of this PR or could we add it in a separate PR?

@thedataking
thedataking requested a review from emilio January 15, 2026 04:34
@workingjubilee

Copy link
Copy Markdown
Member

Good point, I added a test that requires the enum to have a 64-bit value. Any other cases of concern I should add?

In addition to u32::MAX + 1, I believe the other "touchy" cases are

  • an enum with a value in i32::MAX + 1..=u32::MAX
  • the previous enum but also with a negative value (so cannot be represented as u32)
  • in general, enums with both positive and negative values vs. ones with just positive values
  • anything in the i128 or u128 range

And maybe a "control" test for more usual-size enums without short-enums.

See rust-lang/rust#147017 for more on the issue here and the FCW that wound up landing.

@emilio emilio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ok but it seems the tests were failing?

View changes since this review

thedataking pushed a commit to immunant/rust-bindgen that referenced this pull request Aug 30, 2026
@thedataking
thedataking force-pushed the rustified-enum-repr-c branch from a11cced to a76013f Compare August 30, 2026 00:10
@rustbot rustbot added the A-C++ label Aug 30, 2026
@rustbot

rustbot commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@thedataking
thedataking force-pushed the rustified-enum-repr-c branch 2 times, most recently from 873a66f to af02d12 Compare August 30, 2026 01:44
It is not possible to control the repr via custom attributes so add a
new rustified enum variant which does not use repr(u*) or repr(i*).
Using repr(C) is sometimes necessary to bindgen enums used in functions
subject to cross-language CFI checks.

Closes 3263.

Link: https://rcvalle.com/docs/rust-cfi-design-doc/
Signed-off-by: Per Larsen <perlarsen@google.com>
Add layout tests for --rustified-repr-c-enum covering small and large
enum values. Emit size/align asserts during codegen for enums.

Signed-off-by: Per Larsen <perlarsen@google.com>
Rust sizes a fieldless #[repr(C)] enum like the target's default C enum
type, so C/C++ enums with a different layout - e.g. due to
-fshort-enums, an explicit underlying type, or values outside the C int
range - produce ABI-incompatible bindings. Emit a warning during code
generation when such an enum's layout differs from the usual 4 bytes,
and document the caveat on the --rustified-repr-c-enum and
--default-enum-style options. Also list the new rust_repr_c styles in
the invalid enum style error message.

Signed-off-by: Per Larsen <perlarsen@google.com>
Cover an enum value in the i32::MAX+1..=u32::MAX range, an enum mixing
negative and positive values, and one whose mixed-sign values only fit
in 64 bits. The case triggers rustc's repr_c_enums_larger_than_int
future-compatibility lint.

Signed-off-by: Per Larsen <perlarsen@google.com>
@thedataking
thedataking force-pushed the rustified-enum-repr-c branch from af02d12 to 1fc93f6 Compare August 30, 2026 02:27
@thedataking
thedataking requested a review from emilio August 30, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support repr(C) for enums

5 participants