ADR-235: par_iter() Walks a List on Every Core, and Its Lambda Neither Pauses Nor Writes What Is Shared

Status: Accepted Date: September 27, 2026 Answers: #185, par_iter has no entry to demand sync of — step 4 of ADR-105 Refines: ADR-105 D3 (a Par[T] has Seq[T]’s surface, and its lambda must be sync) Related: Part II 12.6, ADR-037 D7 (which count a Shared gets), ADR-312 (user_parallelism), ADR-296 D35 (NK2209)

1. Context

Part II 12.6 promises a data-parallel walk:

let bright = pixels.par_iter()
    .map fn(pixel) { pixel.brightness * 1.5 }
    .filter fn(value) { value > 0.5 }
    .collect()

The type language has Par[T] (ADR-105), and a Par falls back to Seq’s entries. Without an entry for par_iter nothing produces one: the receiver is unknown, the lambda is asked nothing, and a pausing one reaches the lowering’s refusal about a compiler limit.

2. Decisions

D1 — Vec::par_iter is a Par[ref T], and it means the same at both settings.

Vec::par_iter(ref Vec[$T]) -> Par[ref $T] sync ends sized. Everything Seq has, a Par has — map, filter, collect, count, nth, join, rev, take, skip, step_by, zip, and for_each, which Seq has too — and a for over one works out every element and then runs the loop’s body in the list’s order.

A value a parallel lambda captures crosses threads, so a SharedMut it changes through update keeps its atomic count — the sharing analysis (ADR-037 D7) treats a lambda handed to any walk chained onto a par_iter(), or onto a name bound to one, as it treats a spawn body.

D2 — The lambda may not pause (NK2209) or change a name outside it (NK2107).

Changed by ADR-async-5 D24-D26: a lambda of map, filter and for_each may pause, and then runs one task per element; NK2104 is asked of it as of an iteration; NK2107 stands; a lambda of fold or par_pieces still may not pause.

Both are asked at both settings, so a program never means something different at the two.

D3 — join over a walk that does not pause.

Seq::join over a map or a chars() has no counterpart below — the language below’s join is a slice’s — and would reach rustc. nikaia_std::seq::Join, in the prelude under no name, is it.

3. Consequences

A lambda that pauses reaches the lowering’s refusal only where the checker could not resolve what it is handed to.

This site is open source. Improve this page.