Skip to content

fix(scanner): honor signed numeric constants in swagger:enum - #75

Closed
hsdfat wants to merge 1 commit into
go-openapi:masterfrom
hsdfat:fix/3412-negative-enum-constants
Closed

fix(scanner): honor signed numeric constants in swagger:enum#75
hsdfat wants to merge 1 commit into
go-openapi:masterfrom
hsdfat:fix/3412-negative-enum-constants

Conversation

@hsdfat

@hsdfat hsdfat commented Aug 1, 2026

Copy link
Copy Markdown

Go's scanner never produces a negative numeric literal: -1 is a unary minus applied to the literal 1, so a signed const reached the enum collector as *ast.UnaryExpr. findEnumValue type-asserted *ast.BasicLit and skipped anything else, silently dropping every signed member — the enum for a type with -1, 0 and 1 came out as [0, 1].

Unwrap a sign (- or +) around an INT or FLOAT literal and fold it into the text handed to strconv, so the whole int64 range round-trips: -9223372036854775808 parses, whereas negating a parsed 9223372036854775808 would overflow.

Integers are now parsed with base 0, reading the literal exactly as Go wrote it. Base 10 rejected the 0x, 0b and 0o prefixes and _ digit separators outright, and read the legacy 017 octal form as 17 where Go means 15.

A literal whose text does not parse is now reported as unsupported and skipped. It previously became a nil enum member, which puts a null in the emitted spec and can panic go-openapi/spec, whose enum handling reflects on the first member.

Identifiers, including iota-derived constants, remain uncollected: they need go/types const evaluation, which is out of scope here.

contributes go-swagger/go-swagger#3412

Change type

Please select: 🆕 New feature or enhancement|🔧 Bug fix'|📃 Documentation update

Short description

Fixes

Full description

Checklist

  • I have signed all my commits with my name and email (see DCO. This does not require a PGP-signed commit
  • I have rebased and squashed my work, so only one commit remains
  • I have added tests to cover my changes.
  • I have properly enriched go doc comments in code.
  • I have properly documented any breaking change.

@fredbi

fredbi commented Aug 1, 2026

Copy link
Copy Markdown
Member

Thank you. I was precisely writing up a similar fix.

The point is that enums are in a bad state (they've always been).

So your fix addresses the bug you've reported, but it's a narrow sub-case of a wider problem. I realized that yesterday when investigating your issue. Your commit looks very close to the very first commit of a wider fix about enums.

Let's see how it goes today. If the larger fix can be safely merged, tested and fully documented I'll pick mine. Otherwise I'll pick yours as a quick fix to release by monday.

Does it sound like a plan?

Go's scanner never produces a negative numeric literal: `-1` is a unary
minus applied to the literal `1`, so a signed const reached the enum
collector as *ast.UnaryExpr. findEnumValue type-asserted *ast.BasicLit
and skipped anything else, silently dropping every signed member — the
enum for a type with `-1`, `0` and `1` came out as `[0, 1]`.

Unwrap a sign (`-` or `+`) around an INT or FLOAT literal and fold it
into the text handed to strconv, so the whole int64 range round-trips:
`-9223372036854775808` parses, whereas negating a parsed
`9223372036854775808` would overflow.

Integers are now parsed with base 0, reading the literal exactly as Go
wrote it. Base 10 rejected the `0x`, `0b` and `0o` prefixes and `_`
digit separators outright, and read the legacy `017` octal form as 17
where Go means 15.

A literal whose text does not parse is now reported as unsupported and
skipped. It previously became a nil enum member, which puts a null in
the emitted spec and can panic go-openapi/spec, whose enum handling
reflects on the first member.

Identifiers, including iota-derived constants, remain uncollected: they
need go/types const evaluation, which is out of scope here.

contributes go-swagger/go-swagger#3412

Signed-off-by: phatlc <phatle.hsd@gmail.com>
@hsdfat
hsdfat force-pushed the fix/3412-negative-enum-constants branch from 7a59398 to e3d4994 Compare August 1, 2026 08:53
@hsdfat

hsdfat commented Aug 1, 2026

Copy link
Copy Markdown
Author

Thank you. I was precisely writing up a similar fix.

The point is that enums are in a bad state (they've always been).

So your fix addresses the bug you've reported, but it's a narrow sub-case of a wider problem. I realized that yesterday when investigating your issue. Your commit looks very close to the very first commit of a wider fix about enums.

Let's see how it goes today. If the larger fix can be safely merged, tested and fully documented I'll pick mine. Otherwise I'll pick yours as a quick fix to release by monday.

Does it sound like a plan?

Sounds good — a wider fix is the better outcome, enums clearly need it. Happy either way: use mine as the stopgap if the bigger one needs more time, otherwise close this out. If the larger rework lands, one thing worth carrying over: ParseInt was hardcoded to base 10, so 0x/0b/0o/_ literals were dropped and legacy 017 read as 17 instead of 15 — and an unparseable literal became a nil enum member rather than being skipped.

@fredbi fredbi mentioned this pull request Aug 1, 2026
5 tasks
@fredbi

fredbi commented Aug 1, 2026

Copy link
Copy Markdown
Member

@hsdfat I've merged #76 which covers your concerns and some other enum-related limitations (see doc site for the full story). Thanks

@fredbi fredbi closed this Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants