Skip to content

-mm=own: callbacks stored into a class's field or returned - #707

Merged
ASDAlexander77 merged 1 commit into
mainfrom
own-callback-shapes
Oct 28, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
own-callback-shapes

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Callbacks stored into a class's field or returned from a function now compile under -mm=own, as callbacks given on, tested or captured already did. A call through one is checked against the functions that can be there. Spec sections 55–56, and the user doc's limits are updated.

Changes

A callback stored into a class's field (§55). A field of a callback type has a family (collectFieldFamilies):

  • Members: the functions stored into it by name.
  • Sources: the callback parameters given on into it (a constructor's private f, this.f = f in a method), and what functions returning a callback returned.
  • Reads: each read of the field must only be called, tested or given on.
  • When it holds: no other module builds the class, no class extends it, and no object of it becomes an interface, any, object, unknown or a union. Otherwise the field is reached in ways this pass can't see, and its family stays open.
  • The key: a field's family is kept under its class's constructor and -1 - its position (fieldFamilyKey), which no parameter has.

A parameter stored into the field gives it on to the field's family (onlyCalledValue, parameterOf), as an argument does to a callee's parameter.

A callback a function returns (§56). A function whose result is a function value has a result family (collectResultFamilies): what it returns, through its result slot and the block arguments where branches merge. A member's symbol that only flows to the return (flowsToReturn) is passed to this family, not escaped. A call of the function, or a local declared from one and never assigned (givenResult), takes its functions from the result family:

  • when it's passed to another callback family;
  • when it's called directly (resolveCallback now takes the callee value).

One classification (takeFamilyValue) of a value given to a family, shared by parameter, field and result families: a function by name, an optional one not given, a callback parameter given on, or what a function returning a callback returned.

A closure kept in a local and called (const call = (v) => f(v); call(v)) already compiled: the closure is called by name with its box (§54). It gets a test here.

Tests

  • own_callback_shapes walks an array a class holds through four shapes:

    • a closure in a local;
    • a callback stored into a field by a constructor and by a method;
    • callbacks a function returns, called through a local and given on.

    Each walk reads the element again after the call, with churn between steps. It runs under own, rc, gc and none, and own emits no counting. Without these changes it fails under own.

  • Negatives:

    • own_err_callback_field_drops: the callback stored into the field replaces a global array the walk's element may be part of.
    • own_err_callback_returned_drops: the returned callback does the same.
  • Full ctest: 6031 of 6031 pass.

  • DefaultLib under own: 163 passed and 11 skipped (marked not own) out of 174, in release and debug, compiled and under the JIT. That's unchanged.

Not in this PR

A class whose object becomes an interface or any, or that another class extends, keeps its fields' families open. Under own, a callback stored into an object may not capture locals, which would escape with it.

🤖 Generated with Claude Code

- A class field of a callback type has a family (spec 55): the functions
  stored into it by name, the callback parameters given on into it (a
  constructor's `private f`, `this.f = f`) and what functions returning
  one returned. Closed while no other module builds the class, no class
  extends it, and no object of it becomes an interface, `any` or a union.
  A call through the field resolves through it.
- A function returning a function value has a result family (spec 56):
  what it returns through its result slot and merges. A call of it, or a
  local declared from one, given to a family or called, takes from it.
- takeFamilyValue: one classification of a value given to a family, for
  parameter, field and result families.
- Spec sections 55-56, the user doc, and tests: own_callback_shapes (a
  closure in a local, a field set by a constructor and a method, returned
  callbacks), own_err_callback_field_drops, own_err_callback_returned_drops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 3c2c5a1 into main Oct 28, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the own-callback-shapes branch October 28, 2026 01:19
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