Semantic Diff

#8949 Recognize untagged payloads only by annotations and builtin types

3 commits

63ef81c1c95ea4dcbf6bdc72d7e6104498e2a389..pr-8949

237d5bfb3 · Christoph Knittel with Claude Opus 5.5 · Oct 21, 2026

Recognize untagged payloads only by annotations and builtin types

Why

With the stdlib annotated, the classifier's list of stdlib type names only matched types that happen to be printed like a stdlib type, and its name-based dict check took any type named dict for an object.

The list, matched before and after expansion, is gone, and so is the dict check: a payload is recognized by its @instanceOf or @typeOf, or by the builtin type it expands to. Generated code is unchanged for the stdlib's types.

addedDiagnostic a local type named dict

type dict<'a>@unboxed type t = D(dict<int>) | S(string)
js
Before
if (typeof v === "object") { return "D"; } else { return "S"; }
diagnostic
After
This untagged variant definition is invalid: Case D has a payload that is not of one of the recognized shapes (object, array, etc). Then it must be the only case with payloads.
0a2f6d57a · Christoph Knittel with Claude Opus 5.5 · Oct 21, 2026

Test that payloads are not recognized by type name

Why

The classifier used to recognize payloads by the printed path of their type; nothing pinned that it no longer does.

An unannotated local Stdlib_Date.t, which the removed list would have taken for a date, is an unknown payload, and aliases of builtin types are recognized through their expansion.

7d2fd8236 · Christoph Knittel with Claude Opus 5.5 · Oct 22, 2026

Drop the name list from the untagged variants spec

Why

Payloads are now recognized only by annotations and builtin types, so the spec's list of stdlib type names and the fallback to it are gone.

Rule 4 lists promise<_> as the one builtin class and says that a type is never recognized by its name; rule 5 keeps the stdlib's annotations.