diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index c2eb9567..1082ea37 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -153,16 +153,16 @@ impl Struct { /// Attempts to convert this struct to a typedef (only works for transparent structs). pub fn as_typedef(&self) -> Option { if self.is_transparent { - // NOTE: A `#[repr(transparent)]` struct with 2+ NZT fields fails to compile, but 0 - // fields is allowed for some strange reason. Don't emit the typedef in that case. + // NOTE: The rust compiler rejects a `#[repr(transparent)]` struct with 2+ NZST fields, + // but accepts an empty struct (see https://github.com/rust-lang/rust/issues/129029). + // Don't emit the typedef in that case. if let Some(field) = self.fields.first() { return Some(Typedef::new_from_struct_field(self, field)); - } else { - error!( - "Cannot convert empty transparent struct {} to typedef", - self.name() - ); } + error!( + "Cannot convert empty transparent struct {} to typedef", + self.name() + ); } None } @@ -288,7 +288,7 @@ impl Item for Struct { } fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { - if self.is_transparent { + if self.is_transparent && self.fields.len() == 1 { resolver.add_none(&self.path); } else { resolver.add_struct(&self.path); diff --git a/tests/expectations/transparent.c b/tests/expectations/transparent.c index 4743b506..3354bc29 100644 --- a/tests/expectations/transparent.c +++ b/tests/expectations/transparent.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +typedef struct { + +} TransparentEmptyStructure; + #define EnumWithAssociatedConstantInImpl_TEN 10 void root(TransparentComplexWrappingStructTuple a, @@ -32,4 +36,5 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - EnumWithAssociatedConstantInImpl h); + TransparentEmptyStructure h, + EnumWithAssociatedConstantInImpl i); diff --git a/tests/expectations/transparent.compat.c b/tests/expectations/transparent.compat.c index c271f816..1ebe9a03 100644 --- a/tests/expectations/transparent.compat.c +++ b/tests/expectations/transparent.compat.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +typedef struct { + +} TransparentEmptyStructure; + #define EnumWithAssociatedConstantInImpl_TEN 10 #ifdef __cplusplus @@ -36,7 +40,8 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - EnumWithAssociatedConstantInImpl h); + TransparentEmptyStructure h, + EnumWithAssociatedConstantInImpl i); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/transparent.cpp b/tests/expectations/transparent.cpp index 22b5f17b..aa6091ca 100644 --- a/tests/expectations/transparent.cpp +++ b/tests/expectations/transparent.cpp @@ -26,6 +26,10 @@ using TransparentPrimitiveWithAssociatedConstants = uint32_t; constexpr static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO = 0; constexpr static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE = 1; +struct TransparentEmptyStructure { + +}; + constexpr static const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN = 10; extern "C" { @@ -37,6 +41,7 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper e, TransparentPrimitiveWrapper f, TransparentPrimitiveWithAssociatedConstants g, - EnumWithAssociatedConstantInImpl h); + TransparentEmptyStructure h, + EnumWithAssociatedConstantInImpl i); } // extern "C" diff --git a/tests/expectations/transparent.pyx b/tests/expectations/transparent.pyx index ac28206f..839c7742 100644 --- a/tests/expectations/transparent.pyx +++ b/tests/expectations/transparent.pyx @@ -28,6 +28,9 @@ cdef extern from *: const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO # = 0 const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE # = 1 + ctypedef struct TransparentEmptyStructure: + pass + const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN # = 10 void root(TransparentComplexWrappingStructTuple a, @@ -37,4 +40,5 @@ cdef extern from *: TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - EnumWithAssociatedConstantInImpl h); + TransparentEmptyStructure h, + EnumWithAssociatedConstantInImpl i); diff --git a/tests/expectations/transparent_both.c b/tests/expectations/transparent_both.c index 6b3c576b..df9b8a57 100644 --- a/tests/expectations/transparent_both.c +++ b/tests/expectations/transparent_both.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +typedef struct TransparentEmptyStructure { + +} TransparentEmptyStructure; + #define EnumWithAssociatedConstantInImpl_TEN 10 void root(TransparentComplexWrappingStructTuple a, @@ -32,4 +36,5 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - struct EnumWithAssociatedConstantInImpl h); + struct TransparentEmptyStructure h, + struct EnumWithAssociatedConstantInImpl i); diff --git a/tests/expectations/transparent_both.compat.c b/tests/expectations/transparent_both.compat.c index 8d56046f..4acd6677 100644 --- a/tests/expectations/transparent_both.compat.c +++ b/tests/expectations/transparent_both.compat.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +typedef struct TransparentEmptyStructure { + +} TransparentEmptyStructure; + #define EnumWithAssociatedConstantInImpl_TEN 10 #ifdef __cplusplus @@ -36,7 +40,8 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - struct EnumWithAssociatedConstantInImpl h); + struct TransparentEmptyStructure h, + struct EnumWithAssociatedConstantInImpl i); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/transparent_tag.c b/tests/expectations/transparent_tag.c index c76d2a36..2f6dea68 100644 --- a/tests/expectations/transparent_tag.c +++ b/tests/expectations/transparent_tag.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +struct TransparentEmptyStructure { + +}; + #define EnumWithAssociatedConstantInImpl_TEN 10 void root(TransparentComplexWrappingStructTuple a, @@ -32,4 +36,5 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - struct EnumWithAssociatedConstantInImpl h); + struct TransparentEmptyStructure h, + struct EnumWithAssociatedConstantInImpl i); diff --git a/tests/expectations/transparent_tag.compat.c b/tests/expectations/transparent_tag.compat.c index 8329ca8a..508d6ad6 100644 --- a/tests/expectations/transparent_tag.compat.c +++ b/tests/expectations/transparent_tag.compat.c @@ -23,6 +23,10 @@ typedef uint32_t TransparentPrimitiveWithAssociatedConstants; #define TransparentPrimitiveWithAssociatedConstants_ZERO 0 #define TransparentPrimitiveWithAssociatedConstants_ONE 1 +struct TransparentEmptyStructure { + +}; + #define EnumWithAssociatedConstantInImpl_TEN 10 #ifdef __cplusplus @@ -36,7 +40,8 @@ void root(TransparentComplexWrappingStructTuple a, TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - struct EnumWithAssociatedConstantInImpl h); + struct TransparentEmptyStructure h, + struct EnumWithAssociatedConstantInImpl i); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/transparent_tag.pyx b/tests/expectations/transparent_tag.pyx index db0f5d93..15d66f74 100644 --- a/tests/expectations/transparent_tag.pyx +++ b/tests/expectations/transparent_tag.pyx @@ -28,6 +28,9 @@ cdef extern from *: const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO # = 0 const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE # = 1 + cdef struct TransparentEmptyStructure: + pass + const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN # = 10 void root(TransparentComplexWrappingStructTuple a, @@ -37,4 +40,5 @@ cdef extern from *: TransparentComplexWrapper_i32 e, TransparentPrimitiveWrapper_i32 f, TransparentPrimitiveWithAssociatedConstants g, - EnumWithAssociatedConstantInImpl h); + TransparentEmptyStructure h, + EnumWithAssociatedConstantInImpl i); diff --git a/tests/rust/transparent.rs b/tests/rust/transparent.rs index 6dc77c1e..1af6e3f0 100644 --- a/tests/rust/transparent.rs +++ b/tests/rust/transparent.rs @@ -41,6 +41,11 @@ impl TransparentPrimitiveWithAssociatedConstants { #[repr(transparent)] struct TransparentPrimitiveWithAssociatedConstants { bits: u32 } +// https://github.com/rust-lang/rust/issues/129029 the rust compiler (wrongly?) accepts this, but +// cbindgen should nevertheless emit the struct definition instead of a typedef. +#[repr(transparent)] +struct TransparentEmptyStructure; + // Associated constant declared after struct declaration. impl TransparentPrimitiveWithAssociatedConstants { pub const ONE: TransparentPrimitiveWithAssociatedConstants = TransparentPrimitiveWithAssociatedConstants { @@ -63,5 +68,6 @@ pub extern "C" fn root( e: TransparentComplexWrapper, f: TransparentPrimitiveWrapper, g: TransparentPrimitiveWithAssociatedConstants, - h: EnumWithAssociatedConstantInImpl, + h: TransparentEmptyStructure, + i: EnumWithAssociatedConstantInImpl, ) { }