Files
scriptc/tests/diagnostics/maps.ts
T
Malte UblandClaude Opus 5.5 f4a8511dca Compile maybe-promise unions, unknown[] rest parameters, and function-valued Maps and Sets
A union may now hold one promise beside data members (`T | Promise<T>`,
`Promise<R | void> | R | void`). The union tag is the `instanceof Promise`
test, and every operation keeps Node's microtask timing: `await` awaits the
promise arm or takes the one non-thenable turn, an async `return` (block
bodies, concise arrows, then handlers) adopts the promise arm after the
function's own finally blocks, `Promise.resolve` returns the promise arm as
is, and `typeof (u as any).then` reads the tag. Data arms that declare
`then`, two promise arms, and function arms beside a promise stay refused
with diagnostics. Inferred JavaScript literals that mix promises and values
keep the checked-dynamic array.

Rest parameters typed `unknown[]` or `any[]` in TypeScript use the
checked-dynamic variadic ABI that JavaScript rest parameters already use,
including spread forwarding (`(...args) => handler(...args)`).

Functions are now Map values, Map keys and Set elements, compared by
closure identity.

Two pre-existing bugs in the same area are fixed: an async lambda in a
`Promise<void> | void` slot got a `Promise<union>` ABI and threw when called
through the slot, and `return cb()` of such a callback in an async function
dropped the promise instead of adopting it.

The retired-engine 2251 and 2790 diagnostics fixtures (tagged templates
with `any[]` rest tags) now compile and match Node, so they move to the
corpus as 6248 and 6249.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:58:57 -07:00

37 lines
1.3 KiB
TypeScript

// Map support boundaries at lowering. Keep accepted adjacent forms here
// as well so widening the value domain removes its old diagnostic.
// Boolean keys compile alongside the remaining value and method fences.
const byFlag = new Map<boolean, string>();
// Function values compile (closures keep their identity in the slot).
const handlers = new Map<string, () => void>();
// Typed nested Maps retain their identity and are supported.
const nested = new Map<string, Map<string, number>>();
// Boolean-keyed parameter slots share the supported key domain.
function useFlags(m: Map<boolean, number>): number {
return m.size;
}
// Nullable Map views are supported; no diagnostic should appear here.
function maybeMap(cond: boolean): Map<string, number> | undefined {
return undefined;
}
// Maps as array elements now preserve references without a diagnostic.
const rows: Map<string, number>[] = [];
// Maps are not JSON (Node stringifies them as the useless "{}" husk;
// scriptc rejects instead of shipping that).
const m = new Map<string, number>();
console.log(JSON.stringify(m));
// Map methods have no bound-value form — call them directly.
const getter = m.get;
// Reached: collection defers its diagnostics until a reference makes
// them relevant; these references are what makes them count.
useFlags(new Map<boolean, number>());
maybeMap(true);