fix(api): emit bare interface for all sealed-interface unions

Optional fields whose type was a sealed-interface union without an
auto-decode discriminator (BotCommandScope, InputMedia, InputPaidMedia,
InputProfilePhoto, InputStoryContent, InputMessageContent,
InputPollMedia, InputPollOptionMedia, InlineQueryResult,
PassportElementError) were emitted as *<Union> — pointer to interface,
which is a Go anti-pattern: interfaces are already nil-able, and
callers were forced to take addresses of concrete variants.

The codegen path goType() guarded against pointer-wrapping using
knownDiscriminators (only 13 unions with auto-decode dispatch), missing
the 10 marker-only sealed interfaces. New package var
knownInterfaceTypes is built from buildUnionTypeSet at emitter
construction and covers both kinds. goType() now consults that.

Net effect:
- api/methods.gen.go: 3 *BotCommandScope and 2 *InputPollMedia fields
  become bare interface
- api/types.gen.go: 14 *InputMessageContent and 1 *InputPollOptionMedia
  fields become bare interface

Regression tests in api/unionparam_test.go cover both shapes:
direct concrete-variant assignment, and nil omitempty on the bare
interface field.
This commit is contained in:
2026-05-09 19:06:59 +01:00
parent 13ea7097e1
commit 6ab80c27e1
5 changed files with 135 additions and 49 deletions
+5 -5
View File
@@ -1875,7 +1875,7 @@ type SendPollParams struct {
// A JSON-serialized list of special entities that appear in the poll explanation. It can be specified instead of explanation_parse_mode
ExplanationEntities []MessageEntity `json:"explanation_entities,omitempty"`
// Media added to the quiz explanation
ExplanationMedia *InputPollMedia `json:"explanation_media,omitempty"`
ExplanationMedia InputPollMedia `json:"explanation_media,omitempty"`
// Amount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with close_date.
OpenPeriod *int64 `json:"open_period,omitempty"`
// Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with open_period.
@@ -1889,7 +1889,7 @@ type SendPollParams struct {
// A JSON-serialized list of special entities that appear in the poll description, which can be specified instead of description_parse_mode
DescriptionEntities []MessageEntity `json:"description_entities,omitempty"`
// Media added to the poll description
Media *InputPollMedia `json:"media,omitempty"`
Media InputPollMedia `json:"media,omitempty"`
// Sends the message silently. Users will receive a notification with no sound.
DisableNotification *bool `json:"disable_notification,omitempty"`
// Protects the contents of the sent message from forwarding and saving
@@ -3140,7 +3140,7 @@ type SetMyCommandsParams struct {
// A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified.
Commands []BotCommand `json:"commands"`
// A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault.
Scope *BotCommandScope `json:"scope,omitempty"`
Scope BotCommandScope `json:"scope,omitempty"`
// A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands
LanguageCode string `json:"language_code,omitempty"`
}
@@ -3157,7 +3157,7 @@ func SetMyCommands(ctx context.Context, b *client.Bot, p *SetMyCommandsParams) (
// Use this method to delete the list of the bot's commands for the given scope and user language. After deletion, higher level commands will be shown to affected users. Returns True on success.
type DeleteMyCommandsParams struct {
// A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault.
Scope *BotCommandScope `json:"scope,omitempty"`
Scope BotCommandScope `json:"scope,omitempty"`
// A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands
LanguageCode string `json:"language_code,omitempty"`
}
@@ -3174,7 +3174,7 @@ func DeleteMyCommands(ctx context.Context, b *client.Bot, p *DeleteMyCommandsPar
// Use this method to get the current list of the bot's commands for the given scope and user language. Returns an Array of BotCommand objects. If commands aren't set, an empty list is returned.
type GetMyCommandsParams struct {
// A JSON-serialized object, describing scope of users. Defaults to BotCommandScopeDefault.
Scope *BotCommandScope `json:"scope,omitempty"`
Scope BotCommandScope `json:"scope,omitempty"`
// A two-letter ISO 639-1 language code or an empty string
LanguageCode string `json:"language_code,omitempty"`
}