Skip to content

repr(int) enums are currently broken #261

Closed
@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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions