par_iter() Walks a List on Every Core, and Its Lambda Neither Pauses Nor Writes What Is SharedStatus: 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)
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.
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.
user_parallelism = yes it is nikaia_std::par::iter(&xs), a wrapper
over rayon whose surface is exactly Seq’s. collect keeps the list’s
order; the walks rayon has only for a walk of known length go through a list,
so they work after a filter too. A map or a filter allocates nothing
it would not have.no it is the list’s own iter(): nothing runs at once, and nothing
here is used.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.
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.
for over a sequence whose step
does — is NK2209, the code Part III already gave a par_iter lambda
beside a grammar’s action: a core that waits holds its share of the work.NK2107: every core would write it at
once. The way out is a map and a collect, or a SharedMut changed
through update, which the message names. A name the lambda binds itself is
its own.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.
A lambda that pauses reaches the lowering’s refusal only where the checker could not resolve what it is handed to.