Skip to content

An object literal's this-free arrows given for an object type are closures - #722

Merged
ASDAlexander77 merged 2 commits into
mainfrom
own-literal-arrows
Oct 28, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
own-literal-arrows

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

apply({ w: x => x + 1 }) for apply(o: { w: (x: number) => number }), or const o: { w: (x: number) => number } = { w: x => x * 2 }, compiled w as a method whose this is the literal object. Read into the receiver's function-typed field, it became a hybrid_func bound to an object made by ts.New that nothing released. -mm=own rejected every such call ("'this value' borrows a field and cannot be stored, returned or captured").

Change (MLIRGen, markClosureMembers). Some arrow members are now compiled in the literal's first pass as closures in fields, not as methods. That applies when both of these hold:

  • the arrow never says this or super, anywhere inside it, nested functions included. In TypeScript an arrow's this is its surroundings', and 00object_func3 relies on an arrow member's nested function reaching the literal through this, so those arrows stay methods;
  • the literal is made for an object (tuple) type: its receiver, or a generic call's parameter.

Untyped parameters take their types from the receiver's member, as a method's do.

A literal made for an interface, or with no receiver, keeps its members as methods: it may become an interface value, whose vtable is built from them. 00interface_type_tag_in_vtable returns such a literal as a Shape.

Own spec §60. It follows §59, which #721 adds; whichever PR merges second will hit a small conflict at the end of the spec.

Test: own_literal_closures covers a typed local, a parameter, a generic call (f1<T, U>), with and without captures, and several members in one literal. It runs under own, rc, gc and none; own emits no counting. 00object_literal_contextual_lambda still compiles only outside own: its foo({ read: () => s, write: value => s = value + "!" }) calls hand a function a closure that writes a captured string, which own refuses on purpose.

Validated on Windows: ctest 6136/6136, and the default library's release tests pass under gc, rc, none and own.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits October 28, 2026 21:08
…sures

`apply({ w: x => x + 1 })` for `apply(o: { w: (x: number) => number })`, or
`const o: { w: (x: number) => number } = { w: x => x * 2 }`, made `w` a
method taking the literal object as its `this`; read into the receiver's
function-typed field it became a hybrid_func bound to an object made by
ts.New that nothing released, which -mm=own rejected ("borrows a field and
cannot be stored, returned or captured").

An arrow function member that never says `this` or `super` (anywhere in it,
nested functions included; an arrow's `this` is its surroundings', and
00object_func3 relies on one reaching the literal through a nested
function's `this`) is now made in the literal's first pass as a closure in a
field, when the literal is made for an object (tuple) type: its receiver,
or a generic call's parameter (markClosureMembers). Its untyped parameters
take their types from the receiver's member, as a method's do. A literal
made for an interface, or with no receiver, keeps its members methods: it
may become an interface value, whose vtable is built from them.

Own spec section 60. Test own_literal_closures (own, rc, gc, none; own emits
no counting).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	tslang/docs/superpowers/specs/2026-09-24-own-memory-model-design.md
@ASDAlexander77
ASDAlexander77 merged commit d06e449 into main Oct 28, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the own-literal-arrows branch October 28, 2026 21:33
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.

1 participant