From 57330a81e2987ebdb1e6696dba432da759c83e5e Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Wed, 14 Sep 2022 18:33:05 +1200 Subject: [PATCH 1/5] Merge generic enum tags --- src/bindgen/config.rs | 3 ++ src/bindgen/ir/enumeration.rs | 46 +++++++++++++++++-- tests/expectations/merge_generic_tags.both.c | 31 +++++++++++++ .../merge_generic_tags.both.compat.c | 39 ++++++++++++++++ tests/expectations/merge_generic_tags.c | 31 +++++++++++++ .../expectations/merge_generic_tags.compat.c | 39 ++++++++++++++++ tests/expectations/merge_generic_tags.cpp | 28 +++++++++++ tests/expectations/merge_generic_tags.pyx | 23 ++++++++++ tests/expectations/merge_generic_tags.tag.c | 31 +++++++++++++ .../merge_generic_tags.tag.compat.c | 39 ++++++++++++++++ tests/expectations/merge_generic_tags.tag.pyx | 23 ++++++++++ .../merge_generic_tags_with_prefix.both.c | 31 +++++++++++++ ...rge_generic_tags_with_prefix.both.compat.c | 39 ++++++++++++++++ .../merge_generic_tags_with_prefix.c | 31 +++++++++++++ .../merge_generic_tags_with_prefix.compat.c | 39 ++++++++++++++++ .../merge_generic_tags_with_prefix.cpp | 28 +++++++++++ .../merge_generic_tags_with_prefix.pyx | 23 ++++++++++ .../merge_generic_tags_with_prefix.tag.c | 31 +++++++++++++ ...erge_generic_tags_with_prefix.tag.compat.c | 39 ++++++++++++++++ .../merge_generic_tags_with_prefix.tag.pyx | 23 ++++++++++ tests/rust/merge_generic_tags.rs | 8 ++++ tests/rust/merge_generic_tags.toml | 2 + tests/rust/merge_generic_tags_with_prefix.rs | 8 ++++ .../rust/merge_generic_tags_with_prefix.toml | 3 ++ 24 files changed, 634 insertions(+), 4 deletions(-) create mode 100644 tests/expectations/merge_generic_tags.both.c create mode 100644 tests/expectations/merge_generic_tags.both.compat.c create mode 100644 tests/expectations/merge_generic_tags.c create mode 100644 tests/expectations/merge_generic_tags.compat.c create mode 100644 tests/expectations/merge_generic_tags.cpp create mode 100644 tests/expectations/merge_generic_tags.pyx create mode 100644 tests/expectations/merge_generic_tags.tag.c create mode 100644 tests/expectations/merge_generic_tags.tag.compat.c create mode 100644 tests/expectations/merge_generic_tags.tag.pyx create mode 100644 tests/expectations/merge_generic_tags_with_prefix.both.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.both.compat.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.compat.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.cpp create mode 100644 tests/expectations/merge_generic_tags_with_prefix.pyx create mode 100644 tests/expectations/merge_generic_tags_with_prefix.tag.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.tag.compat.c create mode 100644 tests/expectations/merge_generic_tags_with_prefix.tag.pyx create mode 100644 tests/rust/merge_generic_tags.rs create mode 100644 tests/rust/merge_generic_tags.toml create mode 100644 tests/rust/merge_generic_tags_with_prefix.rs create mode 100644 tests/rust/merge_generic_tags_with_prefix.toml diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index c7590355a..55be140d9 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -598,6 +598,8 @@ pub struct EnumConfig { /// Whether to generate empty, private default-constructors for tagged /// enums. pub private_default_tagged_enum_constructor: bool, + /// Whether to only output a single tag enum for generic tagged enums. + pub merge_generic_tags: bool, } impl Default for EnumConfig { @@ -618,6 +620,7 @@ impl Default for EnumConfig { derive_ostream: false, enum_class: true, private_default_tagged_enum_constructor: false, + merge_generic_tags: false, } } } diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index b1b6c044f..527452b73 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -2,7 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use std::cell::Cell; use std::io::Write; +use std::rc::Rc; use syn::ext::IdentExt; @@ -270,8 +272,13 @@ impl EnumVariant { mappings: &[(&Path, &GenericArgument)], config: &Config, ) -> Self { + let name = if config.enumeration.merge_generic_tags { + self.name.clone() + } else { + mangle::mangle_name(&self.name, generic_values, &config.export.mangle) + }; Self::new( - mangle::mangle_name(&self.name, generic_values, &config.export.mangle), + name, self.discriminant.clone(), self.body.specialize(generic_values, mappings, config), self.cfg.clone(), @@ -320,11 +327,15 @@ impl Source for EnumVariant { #[derive(Debug, Clone)] pub struct Enum { pub path: Path, + pub unmangled_path: Path, pub export_name: String, + pub unmangled_export_name: String, pub generic_params: GenericParams, pub repr: Repr, pub variants: Vec, pub tag: Option, + /// Keep track of whether any instance of this enum has had its tag written. + pub tag_written: Rc>, pub cfg: Option, pub annotations: AnnotationSet, pub documentation: Documentation, @@ -433,11 +444,13 @@ impl Enum { }; Ok(Enum::new( + path.clone(), path, generic_params, repr, variants, tag, + Rc::new(Cell::new(false)), Cfg::append(mod_cfg, Cfg::load(&item.attrs)), annotations, Documentation::load(&item.attrs), @@ -447,22 +460,28 @@ impl Enum { #[allow(clippy::too_many_arguments)] pub fn new( path: Path, + unmangled_path: Path, generic_params: GenericParams, repr: Repr, variants: Vec, tag: Option, + tag_written: Rc>, cfg: Option, annotations: AnnotationSet, documentation: Documentation, ) -> Self { let export_name = path.name().to_owned(); + let unmangled_export_name = unmangled_path.name().to_owned(); Self { path, + unmangled_path, export_name, + unmangled_export_name, generic_params, repr, variants, tag, + tag_written, cfg, annotations, documentation, @@ -518,10 +537,16 @@ impl Item for Enum { fn rename_for_config(&mut self, config: &Config) { config.export.rename(&mut self.export_name); + config.export.rename(&mut self.unmangled_export_name); if config.language != Language::Cxx && self.tag.is_some() { // it makes sense to always prefix Tag with type name in C - let new_tag = format!("{}_Tag", self.export_name); + let base_name = if config.enumeration.merge_generic_tags { + &self.unmangled_export_name + } else { + &self.export_name + }; + let new_tag = format!("{}_Tag", base_name); if self.repr.style == ReprStyle::Rust { for variant in &mut self.variants { if let VariantBody::Body { ref mut body, .. } = variant.body { @@ -560,11 +585,16 @@ impl Item for Enum { }; for variant in &mut self.variants { + let export_name = if config.enumeration.merge_generic_tags { + &self.unmangled_export_name + } else { + &self.export_name + }; variant.export_name = - format!("{}{}{}", self.export_name, separator, variant.export_name); + format!("{}{}{}", export_name, separator, variant.export_name); if let VariantBody::Body { ref mut body, .. } = variant.body { body.export_name = - format!("{}{}{}", self.export_name, separator, body.export_name()); + format!("{}{}{}", export_name, separator, body.export_name()); } } } @@ -632,6 +662,7 @@ impl Item for Enum { let monomorph = Enum::new( mangled_path, + self.unmangled_path.clone(), GenericParams::default(), self.repr, self.variants @@ -639,6 +670,7 @@ impl Item for Enum { .map(|v| v.specialize(generic_values, &mappings, library.get_config())) .collect(), self.tag.clone(), + self.tag_written.clone(), self.cfg.clone(), self.annotations.clone(), self.documentation.clone(), @@ -747,6 +779,12 @@ impl Enum { has_data: bool, tag_name: &str, ) { + // Only emit the tag enum once if merge_generic_tags is set. + if config.enumeration.merge_generic_tags && self.tag_written.get() { + return; + } + self.tag_written.set(true); + // Open the tag enum. match config.language { Language::C => { diff --git a/tests/expectations/merge_generic_tags.both.c b/tests/expectations/merge_generic_tags.both.c new file mode 100644 index 000000000..44d4bf42b --- /dev/null +++ b/tests/expectations/merge_generic_tags.both.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +typedef enum COption_Tag { + Some, + None, +} COption_Tag; + +typedef struct COption_u8 { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct COption_u32 { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +void root(struct COption_u8 a, struct COption_u32 b); diff --git a/tests/expectations/merge_generic_tags.both.compat.c b/tests/expectations/merge_generic_tags.both.compat.c new file mode 100644 index 000000000..9b894f945 --- /dev/null +++ b/tests/expectations/merge_generic_tags.both.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +typedef enum COption_Tag { + Some, + None, +} COption_Tag; + +typedef struct COption_u8 { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct COption_u32 { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct COption_u8 a, struct COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags.c b/tests/expectations/merge_generic_tags.c new file mode 100644 index 000000000..657d13f90 --- /dev/null +++ b/tests/expectations/merge_generic_tags.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +typedef enum { + Some, + None, +} COption_Tag; + +typedef struct { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +void root(COption_u8 a, COption_u32 b); diff --git a/tests/expectations/merge_generic_tags.compat.c b/tests/expectations/merge_generic_tags.compat.c new file mode 100644 index 000000000..883ae76dd --- /dev/null +++ b/tests/expectations/merge_generic_tags.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +typedef enum { + Some, + None, +} COption_Tag; + +typedef struct { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(COption_u8 a, COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags.cpp b/tests/expectations/merge_generic_tags.cpp new file mode 100644 index 000000000..4b0e148f0 --- /dev/null +++ b/tests/expectations/merge_generic_tags.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +template +struct COption { + enum class Tag { + Some, + None, + }; + + struct Some_Body { + T _0; + }; + + Tag tag; + union { + Some_Body some; + }; +}; + +extern "C" { + +void root(COption a, COption b); + +} // extern "C" diff --git a/tests/expectations/merge_generic_tags.pyx b/tests/expectations/merge_generic_tags.pyx new file mode 100644 index 000000000..abe34f4b1 --- /dev/null +++ b/tests/expectations/merge_generic_tags.pyx @@ -0,0 +1,23 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + ctypedef enum COption_Tag: + Some, + None, + + ctypedef struct COption_u8: + COption_Tag tag; + uint8_t some; + + + + ctypedef struct COption_u32: + COption_Tag tag; + uint32_t some; + + void root(COption_u8 a, COption_u32 b); diff --git a/tests/expectations/merge_generic_tags.tag.c b/tests/expectations/merge_generic_tags.tag.c new file mode 100644 index 000000000..6dcc1d560 --- /dev/null +++ b/tests/expectations/merge_generic_tags.tag.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +enum COption_Tag { + Some, + None, +}; + +struct COption_u8 { + enum COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +}; + + + +struct COption_u32 { + enum COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +}; + +void root(struct COption_u8 a, struct COption_u32 b); diff --git a/tests/expectations/merge_generic_tags.tag.compat.c b/tests/expectations/merge_generic_tags.tag.compat.c new file mode 100644 index 000000000..94111ed53 --- /dev/null +++ b/tests/expectations/merge_generic_tags.tag.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +enum COption_Tag { + Some, + None, +}; + +struct COption_u8 { + enum COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +}; + + + +struct COption_u32 { + enum COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct COption_u8 a, struct COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags.tag.pyx b/tests/expectations/merge_generic_tags.tag.pyx new file mode 100644 index 000000000..e0acb72b1 --- /dev/null +++ b/tests/expectations/merge_generic_tags.tag.pyx @@ -0,0 +1,23 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef enum COption_Tag: + Some, + None, + + cdef struct COption_u8: + COption_Tag tag; + uint8_t some; + + + + cdef struct COption_u32: + COption_Tag tag; + uint32_t some; + + void root(COption_u8 a, COption_u32 b); diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.c b/tests/expectations/merge_generic_tags_with_prefix.both.c new file mode 100644 index 000000000..9184ae406 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.both.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +typedef enum COption_Tag { + COption_Some, + COption_None, +} COption_Tag; + +typedef struct COption_u8 { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct COption_u32 { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +void root(struct COption_u8 a, struct COption_u32 b); diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.compat.c b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c new file mode 100644 index 000000000..dee4a750f --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +typedef enum COption_Tag { + COption_Some, + COption_None, +} COption_Tag; + +typedef struct COption_u8 { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct COption_u32 { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct COption_u8 a, struct COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags_with_prefix.c b/tests/expectations/merge_generic_tags_with_prefix.c new file mode 100644 index 000000000..f60779aff --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +typedef enum { + COption_Some, + COption_None, +} COption_Tag; + +typedef struct { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +void root(COption_u8 a, COption_u32 b); diff --git a/tests/expectations/merge_generic_tags_with_prefix.compat.c b/tests/expectations/merge_generic_tags_with_prefix.compat.c new file mode 100644 index 000000000..dd8b7b417 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +typedef enum { + COption_Some, + COption_None, +} COption_Tag; + +typedef struct { + COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +} COption_u8; + + + +typedef struct { + COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +} COption_u32; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(COption_u8 a, COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags_with_prefix.cpp b/tests/expectations/merge_generic_tags_with_prefix.cpp new file mode 100644 index 000000000..464bf3179 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +template +struct COption { + enum class Tag { + COption_Some, + COption_None, + }; + + struct COption_Some_Body { + T _0; + }; + + Tag tag; + union { + COption_Some_Body some; + }; +}; + +extern "C" { + +void root(COption a, COption b); + +} // extern "C" diff --git a/tests/expectations/merge_generic_tags_with_prefix.pyx b/tests/expectations/merge_generic_tags_with_prefix.pyx new file mode 100644 index 000000000..ba901f2f6 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.pyx @@ -0,0 +1,23 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + ctypedef enum COption_Tag: + COption_Some, + COption_None, + + ctypedef struct COption_u8: + COption_Tag tag; + uint8_t some; + + + + ctypedef struct COption_u32: + COption_Tag tag; + uint32_t some; + + void root(COption_u8 a, COption_u32 b); diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.c b/tests/expectations/merge_generic_tags_with_prefix.tag.c new file mode 100644 index 000000000..8a5569f26 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +enum COption_Tag { + COption_Some, + COption_None, +}; + +struct COption_u8 { + enum COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +}; + + + +struct COption_u32 { + enum COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +}; + +void root(struct COption_u8 a, struct COption_u32 b); diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c new file mode 100644 index 000000000..963d49098 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +enum COption_Tag { + COption_Some, + COption_None, +}; + +struct COption_u8 { + enum COption_Tag tag; + union { + struct { + uint8_t some; + }; + }; +}; + + + +struct COption_u32 { + enum COption_Tag tag; + union { + struct { + uint32_t some; + }; + }; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct COption_u8 a, struct COption_u32 b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.pyx b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx new file mode 100644 index 000000000..63565e033 --- /dev/null +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx @@ -0,0 +1,23 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef enum COption_Tag: + COption_Some, + COption_None, + + cdef struct COption_u8: + COption_Tag tag; + uint8_t some; + + + + cdef struct COption_u32: + COption_Tag tag; + uint32_t some; + + void root(COption_u8 a, COption_u32 b); diff --git a/tests/rust/merge_generic_tags.rs b/tests/rust/merge_generic_tags.rs new file mode 100644 index 000000000..d82164c0b --- /dev/null +++ b/tests/rust/merge_generic_tags.rs @@ -0,0 +1,8 @@ +#[repr(C)] +pub enum COption { + Some(T), + None, +} + +#[no_mangle] +pub extern "C" fn root(a: COption, b: COption) {} diff --git a/tests/rust/merge_generic_tags.toml b/tests/rust/merge_generic_tags.toml new file mode 100644 index 000000000..5014534dd --- /dev/null +++ b/tests/rust/merge_generic_tags.toml @@ -0,0 +1,2 @@ +[enum] +merge_generic_tags = true diff --git a/tests/rust/merge_generic_tags_with_prefix.rs b/tests/rust/merge_generic_tags_with_prefix.rs new file mode 100644 index 000000000..d82164c0b --- /dev/null +++ b/tests/rust/merge_generic_tags_with_prefix.rs @@ -0,0 +1,8 @@ +#[repr(C)] +pub enum COption { + Some(T), + None, +} + +#[no_mangle] +pub extern "C" fn root(a: COption, b: COption) {} diff --git a/tests/rust/merge_generic_tags_with_prefix.toml b/tests/rust/merge_generic_tags_with_prefix.toml new file mode 100644 index 000000000..57e15f6ce --- /dev/null +++ b/tests/rust/merge_generic_tags_with_prefix.toml @@ -0,0 +1,3 @@ +[enum] +merge_generic_tags = true +prefix_with_name = true From bdf1c26485a0f3140a26d8504b72cf7e3a467d1c Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Tue, 30 May 2023 19:42:21 +1200 Subject: [PATCH 2/5] Remove hidden state used to merge generic tags --- src/bindgen/ir/enumeration.rs | 112 ++++++++++-------- tests/expectations/merge_generic_tags.both.c | 2 - .../merge_generic_tags.both.compat.c | 2 - tests/expectations/merge_generic_tags.c | 2 - .../expectations/merge_generic_tags.compat.c | 2 - tests/expectations/merge_generic_tags.pyx | 2 - tests/expectations/merge_generic_tags.tag.c | 2 - .../merge_generic_tags.tag.compat.c | 2 - tests/expectations/merge_generic_tags.tag.pyx | 2 - .../merge_generic_tags_with_prefix.both.c | 6 +- ...rge_generic_tags_with_prefix.both.compat.c | 6 +- .../merge_generic_tags_with_prefix.c | 6 +- .../merge_generic_tags_with_prefix.compat.c | 6 +- .../merge_generic_tags_with_prefix.pyx | 6 +- .../merge_generic_tags_with_prefix.tag.c | 6 +- ...erge_generic_tags_with_prefix.tag.compat.c | 6 +- .../merge_generic_tags_with_prefix.tag.pyx | 6 +- 17 files changed, 78 insertions(+), 98 deletions(-) diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 527452b73..a02eebf58 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -2,9 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::cell::Cell; use std::io::Write; -use std::rc::Rc; use syn::ext::IdentExt; @@ -272,13 +270,8 @@ impl EnumVariant { mappings: &[(&Path, &GenericArgument)], config: &Config, ) -> Self { - let name = if config.enumeration.merge_generic_tags { - self.name.clone() - } else { - mangle::mangle_name(&self.name, generic_values, &config.export.mangle) - }; Self::new( - name, + mangle::mangle_name(&self.name, generic_values, &config.export.mangle), self.discriminant.clone(), self.body.specialize(generic_values, mappings, config), self.cfg.clone(), @@ -327,15 +320,12 @@ impl Source for EnumVariant { #[derive(Debug, Clone)] pub struct Enum { pub path: Path, - pub unmangled_path: Path, pub export_name: String, - pub unmangled_export_name: String, pub generic_params: GenericParams, pub repr: Repr, pub variants: Vec, pub tag: Option, - /// Keep track of whether any instance of this enum has had its tag written. - pub tag_written: Rc>, + pub external_tag: bool, pub cfg: Option, pub annotations: AnnotationSet, pub documentation: Documentation, @@ -444,13 +434,12 @@ impl Enum { }; Ok(Enum::new( - path.clone(), path, generic_params, repr, variants, tag, - Rc::new(Cell::new(false)), + false, Cfg::append(mod_cfg, Cfg::load(&item.attrs)), annotations, Documentation::load(&item.attrs), @@ -460,28 +449,24 @@ impl Enum { #[allow(clippy::too_many_arguments)] pub fn new( path: Path, - unmangled_path: Path, generic_params: GenericParams, repr: Repr, variants: Vec, tag: Option, - tag_written: Rc>, + external_tag: bool, cfg: Option, annotations: AnnotationSet, documentation: Documentation, ) -> Self { let export_name = path.name().to_owned(); - let unmangled_export_name = unmangled_path.name().to_owned(); Self { path, - unmangled_path, export_name, - unmangled_export_name, generic_params, repr, variants, tag, - tag_written, + external_tag, cfg, annotations, documentation, @@ -537,16 +522,10 @@ impl Item for Enum { fn rename_for_config(&mut self, config: &Config) { config.export.rename(&mut self.export_name); - config.export.rename(&mut self.unmangled_export_name); - if config.language != Language::Cxx && self.tag.is_some() { + if config.language != Language::Cxx && self.tag.is_some() && !self.external_tag { // it makes sense to always prefix Tag with type name in C - let base_name = if config.enumeration.merge_generic_tags { - &self.unmangled_export_name - } else { - &self.export_name - }; - let new_tag = format!("{}_Tag", base_name); + let new_tag = format!("{}_Tag", self.export_name()); if self.repr.style == ReprStyle::Rust { for variant in &mut self.variants { if let VariantBody::Body { ref mut body, .. } = variant.body { @@ -585,16 +564,11 @@ impl Item for Enum { }; for variant in &mut self.variants { - let export_name = if config.enumeration.merge_generic_tags { - &self.unmangled_export_name - } else { - &self.export_name - }; variant.export_name = - format!("{}{}{}", export_name, separator, variant.export_name); + format!("{}{}{}", self.export_name, separator, variant.export_name); if let VariantBody::Body { ref mut body, .. } = variant.body { body.export_name = - format!("{}{}{}", export_name, separator, body.export_name()); + format!("{}{}{}", self.export_name, separator, body.export_name()); } } } @@ -646,6 +620,34 @@ impl Item for Enum { library: &Library, out: &mut Monomorphs, ) { + let config = library.get_config(); + let external_tag = config.enumeration.merge_generic_tags; + + let tag = if external_tag { + let new_tag = format!("{}_Tag", self.export_name()); + let path = Path::new(new_tag.clone()); + + if !out.contains(&GenericPath::new(self.path.clone(), vec![])) { + let tag = Enum::new( + path, + GenericParams::default(), + self.repr, + self.variants.clone(), + None, + false, + self.cfg.clone(), + self.annotations.clone(), + self.documentation.clone(), + ); + + out.insert_enum(library, self, tag, vec![]); + } + + Some(new_tag) + } else { + self.tag.clone() + }; + let mappings = self.generic_params.call(self.path.name(), generic_values); for variant in &self.variants { @@ -662,15 +664,14 @@ impl Item for Enum { let monomorph = Enum::new( mangled_path, - self.unmangled_path.clone(), GenericParams::default(), self.repr, self.variants .iter() .map(|v| v.specialize(generic_values, &mappings, library.get_config())) .collect(), - self.tag.clone(), - self.tag_written.clone(), + tag, + external_tag, self.cfg.clone(), self.annotations.clone(), self.documentation.clone(), @@ -680,6 +681,18 @@ impl Item for Enum { } fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { + if let Some(tag) = self.tag.clone() { + let path = Path::new(tag); + + // If there is an external tag enum, then add it as a dependency. + if let Some(items) = library.get_items(&path) { + if !out.items.contains(&path) { + out.items.insert(path); + out.order.extend(items); + } + } + } + for variant in &self.variants { variant.add_dependencies(library, out); } @@ -706,14 +719,19 @@ impl Source for Enum { self.open_struct_or_union(config, out, inline_tag_field); } - // Emit the tag enum and everything related to it. - self.write_tag_enum(config, out, size, has_data, tag_name); + if !self.external_tag { + // Emit the tag enum and everything related to it. + self.write_tag_enum(config, out, size, has_data, tag_name); + + if has_data { + out.new_line(); + out.new_line(); + } + } // If the enum has data, we need to emit structs for the variants and gather them together. if has_data { self.write_variant_defs(config, out); - out.new_line(); - out.new_line(); // Open the struct or union for the data (**), gathering all the variants with data // together, unless it's C++, then we have already opened that struct/union at (*) and @@ -779,12 +797,6 @@ impl Enum { has_data: bool, tag_name: &str, ) { - // Only emit the tag enum once if merge_generic_tags is set. - if config.enumeration.merge_generic_tags && self.tag_written.get() { - return; - } - self.tag_written.set(true); - // Open the tag enum. match config.language { Language::C => { @@ -925,8 +937,6 @@ impl Enum { .. } = variant.body { - out.new_line(); - out.new_line(); let condition = variant.cfg.to_condition(config); // Cython doesn't support conditional enum variants. if config.language != Language::Cython { @@ -936,6 +946,8 @@ impl Enum { if config.language != Language::Cython { condition.write_after(config, out); } + out.new_line(); + out.new_line(); } } } diff --git a/tests/expectations/merge_generic_tags.both.c b/tests/expectations/merge_generic_tags.both.c index 44d4bf42b..d4227fdab 100644 --- a/tests/expectations/merge_generic_tags.both.c +++ b/tests/expectations/merge_generic_tags.both.c @@ -17,8 +17,6 @@ typedef struct COption_u8 { }; } COption_u8; - - typedef struct COption_u32 { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.both.compat.c b/tests/expectations/merge_generic_tags.both.compat.c index 9b894f945..eea6b2f16 100644 --- a/tests/expectations/merge_generic_tags.both.compat.c +++ b/tests/expectations/merge_generic_tags.both.compat.c @@ -17,8 +17,6 @@ typedef struct COption_u8 { }; } COption_u8; - - typedef struct COption_u32 { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.c b/tests/expectations/merge_generic_tags.c index 657d13f90..3aa8827b7 100644 --- a/tests/expectations/merge_generic_tags.c +++ b/tests/expectations/merge_generic_tags.c @@ -17,8 +17,6 @@ typedef struct { }; } COption_u8; - - typedef struct { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.compat.c b/tests/expectations/merge_generic_tags.compat.c index 883ae76dd..dbbff1ff1 100644 --- a/tests/expectations/merge_generic_tags.compat.c +++ b/tests/expectations/merge_generic_tags.compat.c @@ -17,8 +17,6 @@ typedef struct { }; } COption_u8; - - typedef struct { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.pyx b/tests/expectations/merge_generic_tags.pyx index abe34f4b1..ab0c318d8 100644 --- a/tests/expectations/merge_generic_tags.pyx +++ b/tests/expectations/merge_generic_tags.pyx @@ -14,8 +14,6 @@ cdef extern from *: COption_Tag tag; uint8_t some; - - ctypedef struct COption_u32: COption_Tag tag; uint32_t some; diff --git a/tests/expectations/merge_generic_tags.tag.c b/tests/expectations/merge_generic_tags.tag.c index 6dcc1d560..455089007 100644 --- a/tests/expectations/merge_generic_tags.tag.c +++ b/tests/expectations/merge_generic_tags.tag.c @@ -17,8 +17,6 @@ struct COption_u8 { }; }; - - struct COption_u32 { enum COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.tag.compat.c b/tests/expectations/merge_generic_tags.tag.compat.c index 94111ed53..dee2d2a51 100644 --- a/tests/expectations/merge_generic_tags.tag.compat.c +++ b/tests/expectations/merge_generic_tags.tag.compat.c @@ -17,8 +17,6 @@ struct COption_u8 { }; }; - - struct COption_u32 { enum COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags.tag.pyx b/tests/expectations/merge_generic_tags.tag.pyx index e0acb72b1..5029d2104 100644 --- a/tests/expectations/merge_generic_tags.tag.pyx +++ b/tests/expectations/merge_generic_tags.tag.pyx @@ -14,8 +14,6 @@ cdef extern from *: COption_Tag tag; uint8_t some; - - cdef struct COption_u32: COption_Tag tag; uint32_t some; diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.c b/tests/expectations/merge_generic_tags_with_prefix.both.c index 9184ae406..d5c0fe286 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.both.c +++ b/tests/expectations/merge_generic_tags_with_prefix.both.c @@ -4,8 +4,8 @@ #include typedef enum COption_Tag { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, } COption_Tag; typedef struct COption_u8 { @@ -17,8 +17,6 @@ typedef struct COption_u8 { }; } COption_u8; - - typedef struct COption_u32 { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.compat.c b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c index dee4a750f..ebefb9348 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.both.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c @@ -4,8 +4,8 @@ #include typedef enum COption_Tag { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, } COption_Tag; typedef struct COption_u8 { @@ -17,8 +17,6 @@ typedef struct COption_u8 { }; } COption_u8; - - typedef struct COption_u32 { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.c b/tests/expectations/merge_generic_tags_with_prefix.c index f60779aff..2887f8367 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.c +++ b/tests/expectations/merge_generic_tags_with_prefix.c @@ -4,8 +4,8 @@ #include typedef enum { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, } COption_Tag; typedef struct { @@ -17,8 +17,6 @@ typedef struct { }; } COption_u8; - - typedef struct { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.compat.c b/tests/expectations/merge_generic_tags_with_prefix.compat.c index dd8b7b417..bd3ac220d 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.compat.c @@ -4,8 +4,8 @@ #include typedef enum { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, } COption_Tag; typedef struct { @@ -17,8 +17,6 @@ typedef struct { }; } COption_u8; - - typedef struct { COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.pyx b/tests/expectations/merge_generic_tags_with_prefix.pyx index ba901f2f6..cb671c73a 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.pyx +++ b/tests/expectations/merge_generic_tags_with_prefix.pyx @@ -7,15 +7,13 @@ cdef extern from *: cdef extern from *: ctypedef enum COption_Tag: - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, ctypedef struct COption_u8: COption_Tag tag; uint8_t some; - - ctypedef struct COption_u32: COption_Tag tag; uint32_t some; diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.c b/tests/expectations/merge_generic_tags_with_prefix.tag.c index 8a5569f26..6cbb1798d 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.c +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.c @@ -4,8 +4,8 @@ #include enum COption_Tag { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, }; struct COption_u8 { @@ -17,8 +17,6 @@ struct COption_u8 { }; }; - - struct COption_u32 { enum COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c index 963d49098..a00fc5229 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c @@ -4,8 +4,8 @@ #include enum COption_Tag { - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, }; struct COption_u8 { @@ -17,8 +17,6 @@ struct COption_u8 { }; }; - - struct COption_u32 { enum COption_Tag tag; union { diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.pyx b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx index 63565e033..038ab3af6 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.pyx +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx @@ -7,15 +7,13 @@ cdef extern from *: cdef extern from *: cdef enum COption_Tag: - COption_Some, - COption_None, + COption_Tag_Some, + COption_Tag_None, cdef struct COption_u8: COption_Tag tag; uint8_t some; - - cdef struct COption_u32: COption_Tag tag; uint32_t some; From 9cd7c199191f53b79ac2ea7c77f497b124a8b0c0 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Tue, 30 May 2023 19:53:30 +1200 Subject: [PATCH 3/5] Remove "_Tag" suffix from external tag enum variants --- src/bindgen/ir/enumeration.rs | 28 ++++++++++--------- .../merge_generic_tags_with_prefix.both.c | 4 +-- ...rge_generic_tags_with_prefix.both.compat.c | 4 +-- .../merge_generic_tags_with_prefix.c | 4 +-- .../merge_generic_tags_with_prefix.compat.c | 4 +-- .../merge_generic_tags_with_prefix.pyx | 4 +-- .../merge_generic_tags_with_prefix.tag.c | 4 +-- ...erge_generic_tags_with_prefix.tag.compat.c | 4 +-- .../merge_generic_tags_with_prefix.tag.pyx | 4 +-- 9 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index a02eebf58..7d4185bcb 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -439,7 +439,7 @@ impl Enum { repr, variants, tag, - false, + /* external_tag */ false, Cfg::append(mod_cfg, Cfg::load(&item.attrs)), annotations, Documentation::load(&item.attrs), @@ -557,6 +557,8 @@ impl Item for Enum { if config.enumeration.prefix_with_name || self.annotations.bool("prefix-with-name").unwrap_or(false) { + let prefix = self.export_name.trim_end_matches("_Tag"); + let separator = if config.export.mangle.remove_underscores { "" } else { @@ -564,11 +566,9 @@ impl Item for Enum { }; for variant in &mut self.variants { - variant.export_name = - format!("{}{}{}", self.export_name, separator, variant.export_name); + variant.export_name = format!("{}{}{}", prefix, separator, variant.export_name); if let VariantBody::Body { ref mut body, .. } = variant.body { - body.export_name = - format!("{}{}{}", self.export_name, separator, body.export_name()); + body.export_name = format!("{}{}{}", prefix, separator, body.export_name()); } } } @@ -681,14 +681,16 @@ impl Item for Enum { } fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { - if let Some(tag) = self.tag.clone() { - let path = Path::new(tag); - - // If there is an external tag enum, then add it as a dependency. - if let Some(items) = library.get_items(&path) { - if !out.items.contains(&path) { - out.items.insert(path); - out.order.extend(items); + if self.external_tag { + if let Some(tag) = self.tag.clone() { + let path = Path::new(tag); + + // If there is an external tag enum, then add it as a dependency. + if let Some(items) = library.get_items(&path) { + if !out.items.contains(&path) { + out.items.insert(path); + out.order.extend(items); + } } } } diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.c b/tests/expectations/merge_generic_tags_with_prefix.both.c index d5c0fe286..f0c3078d4 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.both.c +++ b/tests/expectations/merge_generic_tags_with_prefix.both.c @@ -4,8 +4,8 @@ #include typedef enum COption_Tag { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, } COption_Tag; typedef struct COption_u8 { diff --git a/tests/expectations/merge_generic_tags_with_prefix.both.compat.c b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c index ebefb9348..ab9ce6c77 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.both.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.both.compat.c @@ -4,8 +4,8 @@ #include typedef enum COption_Tag { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, } COption_Tag; typedef struct COption_u8 { diff --git a/tests/expectations/merge_generic_tags_with_prefix.c b/tests/expectations/merge_generic_tags_with_prefix.c index 2887f8367..b28f82ede 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.c +++ b/tests/expectations/merge_generic_tags_with_prefix.c @@ -4,8 +4,8 @@ #include typedef enum { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, } COption_Tag; typedef struct { diff --git a/tests/expectations/merge_generic_tags_with_prefix.compat.c b/tests/expectations/merge_generic_tags_with_prefix.compat.c index bd3ac220d..30d91cfb7 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.compat.c @@ -4,8 +4,8 @@ #include typedef enum { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, } COption_Tag; typedef struct { diff --git a/tests/expectations/merge_generic_tags_with_prefix.pyx b/tests/expectations/merge_generic_tags_with_prefix.pyx index cb671c73a..031bc9f42 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.pyx +++ b/tests/expectations/merge_generic_tags_with_prefix.pyx @@ -7,8 +7,8 @@ cdef extern from *: cdef extern from *: ctypedef enum COption_Tag: - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, ctypedef struct COption_u8: COption_Tag tag; diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.c b/tests/expectations/merge_generic_tags_with_prefix.tag.c index 6cbb1798d..a8318f88e 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.c +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.c @@ -4,8 +4,8 @@ #include enum COption_Tag { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, }; struct COption_u8 { diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c index a00fc5229..fa9297fb3 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.compat.c @@ -4,8 +4,8 @@ #include enum COption_Tag { - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, }; struct COption_u8 { diff --git a/tests/expectations/merge_generic_tags_with_prefix.tag.pyx b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx index 038ab3af6..64482ebb8 100644 --- a/tests/expectations/merge_generic_tags_with_prefix.tag.pyx +++ b/tests/expectations/merge_generic_tags_with_prefix.tag.pyx @@ -7,8 +7,8 @@ cdef extern from *: cdef extern from *: cdef enum COption_Tag: - COption_Tag_Some, - COption_Tag_None, + COption_Some, + COption_None, cdef struct COption_u8: COption_Tag tag; From 27c01a4d5c049f8078928b720e63aa28738a9a1d Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 1 Jun 2023 17:05:18 +1200 Subject: [PATCH 4/5] Factor out Dependencies::add_path --- src/bindgen/dependencies.rs | 20 ++++++++++++++++++++ src/bindgen/ir/enumeration.rs | 7 +------ src/bindgen/ir/ty.rs | 19 +------------------ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/bindgen/dependencies.rs b/src/bindgen/dependencies.rs index 6a9873818..78dab6df2 100644 --- a/src/bindgen/dependencies.rs +++ b/src/bindgen/dependencies.rs @@ -7,6 +7,8 @@ use std::collections::HashSet; use crate::bindgen::ir::{ItemContainer, Path}; +use super::library::Library; + /// A dependency list is used for gathering what order to output the types. #[derive(Default)] pub struct Dependencies { @@ -22,6 +24,24 @@ impl Dependencies { } } + pub fn add_path(&mut self, library: &Library, path: &Path) { + if let Some(items) = library.get_items(path) { + if !self.items.contains(path) { + self.items.insert(path.clone()); + + for item in &items { + item.deref().add_dependencies(library, self); + } + self.order.extend(items); + } + } else { + warn!( + "Can't find {}. This usually means that this type was incompatible or not found.", + path + ); + } + } + pub fn sort(&mut self) { // Sort untagged enums and opaque structs into their own layers because they don't // depend on each other or anything else. diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 7d4185bcb..50ca06f2f 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -686,12 +686,7 @@ impl Item for Enum { let path = Path::new(tag); // If there is an external tag enum, then add it as a dependency. - if let Some(items) = library.get_items(&path) { - if !out.items.contains(&path) { - out.items.insert(path); - out.order.extend(items); - } - } + out.add_path(library, &path); } } diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 5a31fb646..aefcd6d43 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -823,24 +823,7 @@ impl Type { } let path = generic.path(); if !generic_params.iter().any(|param| param.name() == path) { - if let Some(items) = library.get_items(path) { - if !out.items.contains(path) { - out.items.insert(path.clone()); - - for item in &items { - item.deref().add_dependencies(library, out); - } - for item in items { - out.order.push(item); - } - } - } else { - warn!( - "Can't find {}. This usually means that this type was incompatible or \ - not found.", - path - ); - } + out.add_path(library, path); } } Type::Primitive(_) => {} From e8373f16de443e3c86a6ef8e55ebf33fea19c962 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 1 Jun 2023 18:05:04 +1200 Subject: [PATCH 5/5] Document merge_generic_tags --- docs.md | 10 ++++++++++ template.toml | 1 + 2 files changed, 11 insertions(+) diff --git a/docs.md b/docs.md index d420f2dbe..676572f1b 100644 --- a/docs.md +++ b/docs.md @@ -900,6 +900,16 @@ derive_tagged_enum_copy_assignment = false # default: false private_default_tagged_enum_constructor = false +# Whether to only output a single tag enum for generic tagged enums. This only +# applies when generics are being monomorphized (i.e. not C++). +# +# For example, an enum monomorph `COption` would normally generate a tag enum +# `COption_u8_Tag`, but with this option enabled all monomorphs of `COption` will +# use the same tag enum, named `COption_Tag`. +# +# default: false +merge_generic_tags = false + diff --git a/template.toml b/template.toml index bc414290e..38d04366d 100644 --- a/template.toml +++ b/template.toml @@ -114,6 +114,7 @@ derive_tagged_enum_destructor = false derive_tagged_enum_copy_constructor = false enum_class = true private_default_tagged_enum_constructor = false +merge_generic_tags = false