ir: a call of List.count goes to the walking Iterate.count slot once a type overrides Iterate.count #705

Open
opened 2026-10-30 21:51:12 +00:00 by orion · 0 comments
Collaborator

Context

Found while building std/tensor (#691, PR #695), which is the first type in the repository to override Iterate.count.

memberInValue (compiler/src/ir/witness.trb) finds a member's slot in the witness table of a trait-typed value by name. A witness table holds every default that some type overrides. Once a type overrides Iterate.count, Iterate.count is in the table of every List<T> value, and a call of List.count through such a value finds that slot by name and runs the walking default instead of the O(1) List.count. In the combined std test run, std/html tokenization of a 1 MiB text, which calls characters.count() per character, becomes quadratic and hangs.

Goal

A by-name match is skipped when it is a different default with a body than the member being called, so the call resolves as it does where nothing overrides Iterate.count.

Acceptance criteria

  • memberInValue skips a slot that is another default with a body than the member called.
  • A regression test that fails without the change: a program in which a type overrides Iterate.count and a List<Int> value is counted; the lowered count call is not a callWitness into the Iterate.count slot.
  • Gates green in both tiers.

Size

One PR, one Conventional Commit: fix(ir): a call of a default is not sent to the slot of the default it replaces.

Dependencies

#691 depends on this.

## Context Found while building `std/tensor` (#691, PR #695), which is the first type in the repository to override `Iterate.count`. `memberInValue` (`compiler/src/ir/witness.trb`) finds a member's slot in the witness table of a trait-typed value by name. A witness table holds every default that some type overrides. Once a type overrides `Iterate.count`, `Iterate.count` is in the table of every `List<T>` value, and a call of `List.count` through such a value finds that slot by name and runs the walking default instead of the O(1) `List.count`. In the combined std test run, `std/html` tokenization of a 1 MiB text, which calls `characters.count()` per character, becomes quadratic and hangs. ## Goal A by-name match is skipped when it is a different default with a body than the member being called, so the call resolves as it does where nothing overrides `Iterate.count`. ## Acceptance criteria - [ ] `memberInValue` skips a slot that is another default with a body than the member called. - [ ] A regression test that fails without the change: a program in which a type overrides `Iterate.count` and a `List<Int>` value is counted; the lowered `count` call is not a `callWitness` into the `Iterate.count` slot. - [ ] Gates green in both tiers. ## Size One PR, one Conventional Commit: `fix(ir): a call of a default is not sent to the slot of the default it replaces`. ## Dependencies #691 depends on this.
Sign in to join this conversation.
No labels
loop
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#705
No description provided.