diff options
author | David Tolnay <dtolnay@gmail.com> | 2022-11-28 06:40:20 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-28 09:40:20 -0500 |
commit | 0a78cde484fd5b6a5bbfd4301b3c4cf043a60a38 (patch) | |
tree | ec24cc604a33a0443999b77335fc29e70a722f2b /bindgen/codegen/mod.rs | |
parent | 95fd17b874910184cc0fcd33b287fa4e205d9d7a (diff) |
Fix name collision between C enum and typedef (#2326)
Fixes #2008.
Example:
```c
enum Enum { Variant };
typedef int16_t Enum;
```
This is valid and idiomatic C (though not valid C++). `cbindgen` uses this idiom as the default C translation of Rust enums, the equivalent of what would be `enum Enum : int16_t { Variant };` in C++.
`bindgen header.h` before:
```rust
pub const Enum_Variant: Enum = 0;
pub type Enum = ::std::os::raw::c_uint;
pub type Enum = i16;
```
```console
error[E0428]: the name `Enum` is defined multiple times
--> generated.rs:3:1
|
2 | pub type Enum = ::std::os::raw::c_uint;
| --------------------------------------- previous definition of the type `Enum` here
3 | pub type Enum = i16;
| ^^^^^^^^^^^^^^^^^^^^ `Enum` redefined here
|
= note: `Enum` must be defined only once in the type namespace of this module
```
After:
```rust
pub const Enum_Variant: Enum = 0;
pub type Enum = i16;
```
Diffstat (limited to 'bindgen/codegen/mod.rs')
-rw-r--r-- | bindgen/codegen/mod.rs | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index b4050637..154d7fd1 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -2709,6 +2709,7 @@ impl<'a> EnumBuilder<'a> { mut attrs: Vec<proc_macro2::TokenStream>, repr: proc_macro2::TokenStream, enum_variation: EnumVariation, + has_typedef: bool, ) -> Self { let ident = Ident::new(name, Span::call_site()); @@ -2741,10 +2742,12 @@ impl<'a> EnumBuilder<'a> { EnumVariation::Consts => { let mut variants = Vec::new(); - variants.push(quote! { - #( #attrs )* - pub type #ident = #repr; - }); + if !has_typedef { + variants.push(quote! { + #( #attrs )* + pub type #ident = #repr; + }); + } EnumBuilder::Consts { variants } } @@ -3157,8 +3160,10 @@ impl CodeGenerator for Enum { } let repr = repr.to_rust_ty_or_opaque(ctx, item); + let has_typedef = ctx.is_enum_typedef_combo(item.id()); - let mut builder = EnumBuilder::new(&name, attrs, repr, variation); + let mut builder = + EnumBuilder::new(&name, attrs, repr, variation, has_typedef); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, Ident>::default(); |