Semantic Diff

#8965 Compare variant literals by their JavaScript value

1 commit

b123b7c38f8d78ba50fa3a8044fa63aafe83faab..pr-8965

69f57c00e · Christoph Knittel with Claude Opus 5.5 · Oct 22, 2026

Compare variant literals by their JavaScript value

Why

The duplicate-literal check compared @as literals by spelling, so it accepted @as(1) A | @as(1.0) B, two cases with the same runtime value that a dispatched B matches as A (#8953), and rejected @as(1) A | @as(1n) B, two different values.

Literals other than strings are now keyed by the value a switch compares with ===: an int as the 32-bit number it is emitted as, a float as the number it parses to, with -0. and 0 equal, and a bigint by its normalized digits, apart from numbers. Constant folding uses the same key, so a constant bigint case now folds too. The spec's rule 6 states the comparison, and the known bug is gone.

addedDiagnostic same value, different spelling

@unboxed type t = | @as(1) A | @as(1.0) B
diagnostic
After
This untagged variant definition is invalid: The literal 1.0 is the same JavaScript value as 1.

removedDiagnostic a number and a bigint

@unboxed type t = | @as(1) One | @as(1n) OneN | S(string)
diagnostic
Before
This untagged variant definition is invalid: Duplicate literal 1.