Skip to content

repr(int) enums are currently broken #261

@petertodd

Description

@petertodd

See rust-lang/rust#56619

Here's an example, lib.rs:

#![allow(dead_code)]

#[repr(u8)]
pub enum Foo {
    A { 
        a: u16,
        b: u8, 
    },  
    B,  
}

extern "C" {
    fn foo() -> Foo;
}

Foo is actually laid out as:

$ cargo rustc -- -Z print-type-sizes
   Compiling foo v0.1.0 (/tmp/foo)
print-type-size type: `Foo`: 4 bytes, alignment: 2 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `A`: 3 bytes
print-type-size         field `.b`: 1 bytes
print-type-size         field `.a`: 2 bytes
print-type-size     variant `B`: 0 bytes
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s

...with b and a of the A variant reversed. Meanwhile cbindgen happily produces a binding with those fields in the wrong order:

$ cbindgen foo
#include <cstdint>
#include <cstdlib>

union Foo {
  enum class Tag : uint8_t {
    A,
    B,
  };

  struct A_Body {
    Tag tag;
    uint16_t a;
    uint8_t b;
  };

  struct {
    Tag tag;
  };
  A_Body a;
};

extern "C" {

extern Foo foo();

} // extern "C"

A decent temporary fix would be to temporarily disable repr(int) enums with variants containing multiple fields of different types until rustc fixes this; if every field is the same type the ordering isn't changed. Similarly single-field variants are also fine because they can't be reordered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions