Owning Iterator Loops v1
September 10, 2026 ยท View on GitHub
Status: implemented bounded traversal; HOSTED GREEN under the v0.4.0 release baseline.
Audience: language users, compiler contributors, backend implementers, and workspace-service authors.
This LANG-07 profile adds one consuming traversal form over the existing private scalar iterator protocol:
for own item in iterator { body }
It is distinct from the frozen bounded-Vec traversal spelling for item in values { body }. The older syntax, cache bytes, lowering, and contracts retain
their exact meaning.
Admission and evaluation
The source expression must produce own Iter<T> and is evaluated once. It is
consumed at loop entry; the old source binding cannot be used after that
transfer. T is one of the eight Copy scalar types admitted by Owning
Iterators v1. item is an immutable per-iteration binding. The body may update
ordinary mutable scalar accumulators and use existing same-owner Vec<T>
assignment rules, but it cannot introduce a second owner for the iterator.
Conditional same-owner Vec renewal inside an authenticated for own body is
specified separately by Owning Iterator Renewal v1.
The lowering has a hidden IterStep<T> slot. Each condition borrows that slot:
Done terminates and Yield enters the body. A Yield transfers its rest
iterator owner into the next hidden iteration state only after the body has
completed; the yielded item remains a Copy binding. The next iteration calls
iter_next(rest) exactly once. This preserves source order and requires exact
ownership equality at every loop boundary.
If the body fails, the selected status remains sticky and cleanup destroys the
remainder exactly once. A failing iter_next read occurs before its transfer
commit, so the staged iterator remains available to canonical failure cleanup.
No loop result is published on either failure path.
Projections and compatibility
CleanupPlan v11 is additive over v10 and records the hidden step/remainder
lifecycle required by this loop. Graph v39 and ProgramRoot retain the checked
consuming-loop source shape, hidden ownership boundary, selected prelude, and
v11 cleanup facts. Earlier cleanup, graph, AST-cache, and canonical source
bytes remain frozen; the new AST cache carrier is additive and cannot reinterpret
the old for tag.
Graphs, caches, plans, and externally supplied lowering bytes carry no authority. Source, HIR, cleanup replay, and each backend independently verify the same ownership boundary before execution.
Exclusions and required evidence
This v1 profile has no break or continue, owned payload elements, iterator
adapters, general authored iterator implementations, or public iterator ABI.
The implemented Bytes payload extension
and generic iterator operations retain
their own admission and schema boundaries.
Focused evidence must cover all eight scalar types, empty and exhausted
iterators, ordered accumulation, source use-after-consume rejection, body and
iter_next failure settlement, repeated invocation, v11/Graph-v39 hostile
replay, and interpreter, C11 O0/O2, and Core Wasm equivalence.
The maintained iterator selector covers the eight-scalar interpreter, C11 O0/O2, and Core-Wasm corpus, including captured generic callbacks, vector accumulation, empty/multiple-yield loops, body-contract failure, repeated settlement, and consumed-source rejection. The workspace selector also verifies private generic loop instances and exact ProgramRoot/source replay. Its release evidence is hosted green; the original focused local runs remain historical witnesses rather than the current evidence ceiling.