You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Confirmed bug. Generated struct conflicts with generated enum variant. See reproduction below for more details. I think this will be a pretty straightforward fix, just a matter of deciding the best way to prevent name collisions between types. I'm going to allocate some cycles this week to think about this and report back with some possible solutions.
It looks like this issue is part of a larger pattern that needs to be addressed. I've summarized my findings below, and I made a comprehensive reproduction. @dicej@jfleitz if you have the time, I'd be grateful to have more eyes on this, as my proposed fixes will result in some larger breaking changes.
Scenario 1: Reserved function name collisions with bindings generated from user-defined WIT types.
The issue is that variants and resources have reserved function names that have the potential to collide with user-defined WIT types.
To avoid unecessary breaking changes, I propose that we fix this by suffixing each colliding user-defined function with an underscore (_). I think it would also be smart to add a doc comment to the colliding user-defined function and print a message to the console to notify the user that their function has been mangled.
These are the current reserved functions that have a risk of collision:
variant.Tag()
resource.TakeHandle()
resource.SetHandle
resource.Handle()
resource.Drop()
resource.OnDrop
Scenario 2: Collisions between bindings generated from enum-like types and other user-defined types
The issue is specific to the enum-like WIT types (enum, variant, and flags) and any user-defined types that can be defined in a world or interface (excluding WIT functions). The WIT parser doesn't catch this because the generated bindings for these types create Go consts that are a concatenation of the name of the type and the type's variants, which then have the potential to collide with another user-defined type.
I propose we fix this by formatting the consts generated for the enum-like types as "{TypeName}_{Case}" as opposed to "{TypeName}{Case}". If we can't think of a better way to handle the collisions, this will be a pretty sizeable breaking change
To avoid unecessary breaking changes, I propose that we fix this by suffixing each colliding user-defined function with an underscore (_). I think it would also be smart to add a doc comment to the colliding user-defined function and print a message to the console to notify the user that their function has been mangled.
👍 Sounds good to me.
Scenario 2: Collisions between bindings generated from enum-like types and other user-defined types
I'm not sure I understand the problem here. It's always possible to add definitions to a Go package which conflict with names in other Go packages, but that's one of the reasons the languages has packages: to provide multiple, separated name spaces instead of just a single global name space. If a developer needs to use two packages that declare different types with the same name, they can import the packages with different names and qualify the identifiers using those names, avoiding any conflict or ambiguity.
The only difference in this case as that the package is generated from WIT input, but we can still rely on the name spacing provided by the Go package system just as if the code was hand-written. Am I missing something?
This generates a package that has a type collision due to the const created for the variant a-b's c case:
package example;
// COMPILE ERROR: ABC redeclared in this block// This is the record structtypeABCstruct {
}
// This is the variant structtypeABstruct {
taguint8valueany
}
// This is the variant case `c`const (
ABCuint8=0
)
To avoid unecessary breaking changes, I propose that we fix this by suffixing each colliding user-defined function with an underscore (_). I think it would also be smart to add a doc comment to the colliding user-defined function and print a message to the console to notify the user that their function has been mangled.
👍 this sounds good to me too.
On the second scenario, thank you @asteurer ! I was just going to ask if it was the collision within the generated struct prior to where implements/go package naming would come into play. So the generated code already has a breaking change. The _ between type and name seems consistent for this too.
@dicej these collisions actually happen inside of the same package.
Ah, I see now. Yeah, I hit the same issue with componentize-py and used the {TypeName}_{Case} approach you described. It was a breaking change there just as it would be here, but seems like the right thing to do.
@QuantumSegfault The fix for this just got merged. If this resolves your issue, you're welcome to close it; otherwise, feel free to share what I might have missed!
Activity
QuantumSegfault commentedon Sep 20, 2026
@asteurer
You seem to be the maintainer of the Go bindgen?
asteurer commentedon Sep 20, 2026
Thanks for tagging me @QuantumSegfault! Here's what I found:
Scenario 1: Enum variant named
tagConfirmed bug. Generated getter method name collides with built-in
Tagmethod. Here's what I did to reproduce:This is the WIT I used:
These are the resulting bindings:
Scenario 2: Conflicting records and enums
Confirmed bug. Generated struct conflicts with generated enum variant. See reproduction below for more details. I think this will be a pretty straightforward fix, just a matter of deciding the best way to prevent name collisions between types. I'm going to allocate some cycles this week to think about this and report back with some possible solutions.
Here's the WIT I used:
Resulting bindings:
QuantumSegfault commentedon Sep 20, 2026
Try giving
taga payload, so it generates a getter for that member's payload.asteurer commentedon Sep 21, 2026
Ah, yep that's definitely a bug. I'll update the summary above and take a look this week.
asteurer commentedon Sep 21, 2026
Overview
It looks like this issue is part of a larger pattern that needs to be addressed. I've summarized my findings below, and I made a comprehensive reproduction. @dicej @jfleitz if you have the time, I'd be grateful to have more eyes on this, as my proposed fixes will result in some larger breaking changes.
Scenario 1: Reserved function name collisions with bindings generated from user-defined WIT types.
The issue is that
variantsandresourceshave reserved function names that have the potential to collide with user-defined WIT types.To avoid unecessary breaking changes, I propose that we fix this by suffixing each colliding user-defined function with an underscore (
_). I think it would also be smart to add a doc comment to the colliding user-defined function and print a message to the console to notify the user that their function has been mangled.These are the current reserved functions that have a risk of collision:
variant.Tag()resource.TakeHandle()resource.SetHandleresource.Handle()resource.Drop()resource.OnDropScenario 2: Collisions between bindings generated from enum-like types and other user-defined types
The issue is specific to the enum-like WIT types (
enum,variant, andflags) and any user-defined types that can be defined in a world or interface (excluding WITfunctions). The WIT parser doesn't catch this because the generated bindings for these types create Goconsts that are a concatenation of the name of the type and the type's variants, which then have the potential to collide with another user-defined type.I propose we fix this by formatting the
consts generated for the enum-like types as"{TypeName}_{Case}"as opposed to"{TypeName}{Case}". If we can't think of a better way to handle the collisions, this will be a pretty sizeable breaking changedicej commentedon Sep 21, 2026
👍 Sounds good to me.
I'm not sure I understand the problem here. It's always possible to add definitions to a Go package which conflict with names in other Go packages, but that's one of the reasons the languages has packages: to provide multiple, separated name spaces instead of just a single global name space. If a developer needs to use two packages that declare different types with the same name, they can import the packages with different names and qualify the identifiers using those names, avoiding any conflict or ambiguity.
The only difference in this case as that the package is generated from WIT input, but we can still rely on the name spacing provided by the Go package system just as if the code was hand-written. Am I missing something?
asteurer commentedon Sep 21, 2026
@dicej these collisions actually happen inside of the same package. Take this interface for example:
This generates a package that has a type collision due to the const created for the variant
a-b'sccase:jfleitz commentedon Sep 21, 2026
👍 this sounds good to me too.
On the second scenario, thank you @asteurer ! I was just going to ask if it was the collision within the generated struct prior to where implements/go package naming would come into play. So the generated code already has a breaking change. The
_between type and name seems consistent for this too.dicej commentedon Sep 21, 2026
Ah, I see now. Yeah, I hit the same issue with
componentize-pyand used the{TypeName}_{Case}approach you described. It was a breaking change there just as it would be here, but seems like the right thing to do.asteurer commentedon Sep 21, 2026
Sounds good. Thank you both for your input!
asteurer commentedon Sep 22, 2026
@QuantumSegfault The fix for this just got merged. If this resolves your issue, you're welcome to close it; otherwise, feel free to share what I might have missed!
QuantumSegfault commentedon Sep 22, 2026
I'll take a look when I get the chance