parallel: the Plain marker (CONCURRENCY gap 4, part of slice F) #155

Closed
opened 2026-10-07 15:41:24 +00:00 by orion · 4 comments
Collaborator

Context

Gap 4 of CONCURRENCY.md, the first part of slice F, split out of #4: the marker Plain, a bound that says "nothing reference counted inside". It is what lets a worker hold a borrowed pointer into the caller's heap without a count change (CONCURRENCY.md section 6, rule R2).

Source

  • CONCURRENCY.md gap 4 and section 6, R2
  • The name was decided on 2026-09-22 (CONCURRENCY.md section 15, question 3). Gap 4b (a borrowed element that is itself counted) is explicitly not part of this issue.

Goal

A trait Plain in std/core that the checker grants to exactly the types whose layout has containsCounted == false, usable as a bound (Item: Plain), and never implementable by a user.

Acceptance criteria

  • Plain is declared in std/core and is importable by name; the checker answers T: Plain from the layout, the way it answers a derived Show (semantics/checker/derive.trb), with no entry in any witness table.
  • Granted: Int, Float, Bool, the sized numbers, Array<Float, 16>, a record or variant whose fields are all Plain, a tuple of them.
  • Refused with a diagnostic that names the reason (which field or case holds the counted type): String, List<_>, Map<_, _>, a record with one of those inside, every shared type, every trait-typed value, a function value.
  • A user with Plain or extend ... with Plain is an error that says the compiler grants it.
  • A type parameter Item: Plain accepts exactly the granted types at the call site, and inside the generic body Item is known to be uncounted (probe: a generic fn first<Item: Plain>(items: List<Item>): Item checks and runs for Int and Point, is refused for String).
  • Checker tests for every bullet above; a trb error block in docs/ for the refusal diagnostic; docs check docs green.
  • The answer is the same in both back ends (it is a checker fact, so a conformance program that uses the bound at run time suffices).

Touches the seed?

  • It adds a std name the checker resolves by string (like Show in derive.trb and wellknown.trb), but additively. One commit, no seed refresh, provided compiler/src and std/ do not themselves use Plain as a bound in this commit (the seed compiler builds them and does not know the trait yet). std/parallel will use it in the follow-up (#4), after a seed refresh that is the owner's call.
  • No syntax change, no new native, no driver flag.

Size

One PR, one Conventional Commit: feat(checker): grant Plain for a layout without counted fields. Touches compiler/src/semantics/checker and std/core; the layout predicate already exists on the IR side (containsCountedType), the checker needs the same fixpoint (as it already computes containsShared). Implementer: opus/high (compiler/src). Worker: both gates a and b if the layout walk is shared with compiler/src/ir.

Dependencies

None.

Part of #4.

## Context Gap 4 of CONCURRENCY.md, the first part of slice F, split out of #4: the marker `Plain`, a bound that says "nothing reference counted inside". It is what lets a worker hold a borrowed pointer into the caller's heap without a count change (CONCURRENCY.md section 6, rule R2). ## Source - [CONCURRENCY.md gap 4](https://git.torb.dev/torbscript/language/src/commit/61d7075c05bd85fd27c71a4c191dd7a9fd5af4c0/docs/design/CONCURRENCY.md#L1137) and [section 6, R2](https://git.torb.dev/torbscript/language/src/commit/61d7075c05bd85fd27c71a4c191dd7a9fd5af4c0/docs/design/CONCURRENCY.md#L411) - The name was decided on 2026-09-22 (CONCURRENCY.md section 15, question 3). Gap 4b (a borrowed element that is itself counted) is explicitly not part of this issue. ## Goal A trait `Plain` in `std/core` that the checker grants to exactly the types whose layout has `containsCounted == false`, usable as a bound (`Item: Plain`), and never implementable by a user. ## Acceptance criteria - [ ] `Plain` is declared in `std/core` and is importable by name; the checker answers `T: Plain` from the layout, the way it answers a derived `Show` (`semantics/checker/derive.trb`), with no entry in any witness table. - [ ] Granted: `Int`, `Float`, `Bool`, the sized numbers, `Array<Float, 16>`, a record or variant whose fields are all `Plain`, a tuple of them. - [ ] Refused with a diagnostic that names the reason (which field or case holds the counted type): `String`, `List<_>`, `Map<_, _>`, a record with one of those inside, every `shared type`, every trait-typed value, a function value. - [ ] A user `with Plain` or `extend ... with Plain` is an error that says the compiler grants it. - [ ] A type parameter `Item: Plain` accepts exactly the granted types at the call site, and inside the generic body `Item` is known to be uncounted (probe: a generic `fn first<Item: Plain>(items: List<Item>): Item` checks and runs for `Int` and `Point`, is refused for `String`). - [ ] Checker tests for every bullet above; a `trb error` block in `docs/` for the refusal diagnostic; `docs check docs` green. - [ ] The answer is the same in both back ends (it is a checker fact, so a conformance program that uses the bound at run time suffices). ## Touches the seed? - It adds a std name the checker resolves by string (like `Show` in `derive.trb` and `wellknown.trb`), but additively. **One commit, no seed refresh**, provided `compiler/src` and `std/` do not themselves use `Plain` as a bound in this commit (the seed compiler builds them and does not know the trait yet). `std/parallel` will use it in the follow-up (#4), after a seed refresh that is the owner's call. - No syntax change, no new native, no driver flag. ## Size One PR, one Conventional Commit: `feat(checker): grant Plain for a layout without counted fields`. Touches `compiler/src/semantics/checker` and `std/core`; the layout predicate already exists on the IR side (`containsCountedType`), the checker needs the same fixpoint (as it already computes `containsShared`). Implementer: opus/high (`compiler/src`). Worker: both gates `a` and `b` if the layout walk is shared with `compiler/src/ir`. ## Dependencies None. Part of #4.
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261007 until 2026-10-07T22:22:45Z

[loop:torbscript] claim implement by session:loop-torbscript-20261007 until 2026-10-07T22:22:45Z
Author
Collaborator

[loop:torbscript] implement: Plain is granted by the checker from the layout (numbers except Decimal, Bool, Char, Array of a plain item, and records, variants and tuples of plain fields). Refusals name the field chain and the counted type, and a written with Plain is an error. Includes the trait in std/core, docs, 21 checker tests and a conformance program, in one commit with no seed refresh. Locally: nightly check clean, 2630 compiler tests pass (the 20 failures are the VM-only torb_machine_install tests), and the new checker in the VM passes the conformance file. There is no C toolchain here, so the A/B gates and the conformance run are left to CI, which is queued. PR #160, next: review. Token usage: not readable from this session.

[loop:torbscript] implement: `Plain` is granted by the checker from the layout (numbers except `Decimal`, `Bool`, `Char`, `Array` of a plain item, and records, variants and tuples of plain fields). Refusals name the field chain and the counted type, and a written `with Plain` is an error. Includes the trait in `std/core`, docs, 21 checker tests and a conformance program, in one commit with no seed refresh. Locally: nightly check clean, 2630 compiler tests pass (the 20 failures are the VM-only `torb_machine_install` tests), and the new checker in the VM passes the conformance file. There is no C toolchain here, so the A/B gates and the conformance run are left to CI, which is queued. PR https://git.torb.dev/torbscript/language/pulls/160, next: review. Token usage: not readable from this session.
Author
Collaborator

[loop:torbscript] claim review by session:loop-torbscript-20261007 until 2026-10-07T21:20:05Z

[loop:torbscript] claim review by session:loop-torbscript-20261007 until 2026-10-07T21:20:05Z
Author
Collaborator

[loop:torbscript] review: tier A was red on c9ed0a6. The fix worker was interrupted by a restart before writing its result, but it had already pushed 557d7ce to loop/155-plain-marker: the same single commit feat(checker): grant Plain for a layout without counted fields, rebased onto main 9e2ab91. The old commit rewrote whole files such as compiler/src/semantics/checker/context.trb; the new one is a clean 16-file change (+952/-13). Forge CI on 557d7ce is running. Worker token usage is not measurable. Claim 604 released, next: waiting (CI on 557d7ce, then the merge gate)

[loop:torbscript] review: tier A was red on c9ed0a6. The fix worker was interrupted by a restart before writing its result, but it had already pushed 557d7ce to `loop/155-plain-marker`: the same single commit `feat(checker): grant Plain for a layout without counted fields`, rebased onto main 9e2ab91. The old commit rewrote whole files such as `compiler/src/semantics/checker/context.trb`; the new one is a clean 16-file change (+952/-13). Forge CI on 557d7ce is running. Worker token usage is not measurable. Claim 604 released, next: waiting (CI on 557d7ce, then the merge gate)
argus closed this issue 2026-10-07 22:36:18 +00:00
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#155
No description provided.