Files
scriptc/tests/corpus/8418-map-closure-elements.ts
T
Malte UblandClaude Opus 5.5 c3954d4dd4 Give a .map callback that answers a closure an ordinary function element
`entries.map((entry) => async () => …)` (package-manager's concurrency task
lists, `(() => Promise<…>)[]`) was refused: `.map` rejected a `func` return
with the same badType as a `void` return.

A closure is a supported array element. The closure array literal `[() => 1]`
already lowers to a `func`-element array, where the value is one ScrClosure
for its whole life, stored by reference with the element kind's `_v` adapter
and `scr_closure_trace_v`. The map helper builds the same array, so the
`func` half of the fence goes at both `.map` sites (plain receiver and
union-of-arrays receiver).

The `void` fence stays: `void[]` has no element, because a void return value
is erased before it could be written.

Corpus 8415-map-closure-elements pins the `.map`-produced arrays of closures:
`Array<() => Promise<string>>` and `Array<() => string>`, closure identity
through `indexOf`/`includes`, an inline `.map`, and
`Promise.all(tasks.map((task) => task()))`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:17:13 -07:00

39 lines
1.3 KiB
TypeScript

// `Array.prototype.map` whose callback answers a CLOSURE: the result is an
// array of functions (`Array<() => Promise<T>>`, the runWithConcurrency
// task-list shape), each element one ScrClosure stored by reference.
interface Entry {
source: string;
scope: "user" | "project";
}
function tasksFor(entries: Entry[]): Array<() => Promise<string>> {
return entries.map((entry) => async () => `${entry.scope}:${entry.source}`);
}
function same(entries: Entry[]): Array<() => string> {
return entries.map((entry) => () => entry.source);
}
async function main(): Promise<void> {
const entries: Entry[] = [
{ source: "a", scope: "user" },
{ source: "b", scope: "project" },
];
const tasks = tasksFor(entries);
for (const task of tasks) console.log("task", await task());
const readers = same(entries);
// A function value is one closure for its whole life: identity through
// indexOf/includes holds.
const first = readers[0];
console.log("identity", readers.indexOf(first!), readers.includes(first!));
if (first) console.log("called", first());
const inline = entries.map((entry) => () => entry.source.length);
console.log("inline", inline.map((read) => read()).join(","));
const results = await Promise.all(tasks.map((task) => task()));
console.log("all", results.join(","));
}
void main();