Result: partial
Files: crates/nikaia-std/src/task.rs crates/nikaia-std/src/task/group.rs crates/nikaia-std/std.contracts tests/compiler/tests/group_scope_reads_three_results_in_order.nika tests/compiler/tests/group_scope_reads_three_results_in_order.stdout tests/compiler/tests/group_scope_raises_an_unread_failure_at_its_end.nika tests/compiler/tests/group_scope_raises_an_unread_failure_at_its_end.stdout tests/compiler/tests/group_scope_keeps_two_failures.nika tests/compiler/tests/group_scope_keeps_two_failures.stdout
Commit: std: the async-5 group runtime and task::ChildHandle / deferred start (#987 steps 1, 2)
Body: New module task/group.rs, the group every scope runs on (D1, D3, D9, D20, D21): Ended {Value, Failed, Crashed, Cancelled, OverBudget (reserved)}; Group (was task.rs Seen; new, start, absorb, crash), ended and ran moved from task.rs; trait Receiver (place, crashed, unread), the hook a handle reports to its group by; Slot/empty_slot, settle, run_now, Unended::drop, paused_task (async fn); ChildHandle (now, deferred_now, paused, start, cancel, join, Drop: a never-joined handle’s failure goes to the group as unread, D11); Deferred (new, cancel, detach, start, start_on_pool, join; the deferred detached handle of D12/D13, a second start panics). task.rs changed: Seen renamed to Group in Scope, PoolScope, PausedScope, PausedPoolScope; Scope::spawn and PausedScope::spawn use Group::absorb; added Scope::{handle, deferred}, PausedScope::{handle, deferred, handle_paused, deferred_paused}, impl Receiver for Scope and PausedScope: the entry points #988’s lowering calls. std.contracts declares task::ChildHandle with join/cancel/start (no TaskHandle::start: without NK2121 of #986 it would let every spawn handle take start()). task::scope behaviour unchanged.
Part: #987
Tests: 3 new tests/compiler programs (three results in order; unread failure raised at the group’s end after the group’s function ran on; two failures, first in start order thrown, all tasks ran), both settings, pass on old and new binary (they guard the scope’s behaviour over the move, so they did not fail before it); the secondary of the two-failures case is diagnostic only (Part I 7.1), shown by the existing it test process_exit SCOPE_JOINS; handles (step 2) have no Nikaia surface until #988, their cases (join value/failure, cancel, drop unjoined -> unread, deferred start, second start panics, paused handle cancel) were run as temporary nikaia-std unit tests and removed (no new Rust #[test]); cargo test -p nikaia-std –lib task:: 7 passed; tests/compiler –both-settings 642 passed 0 failed; it task/overlap/spawn/scope 72 passed; guards range_spelling, shipped_ledger, contracts::, sequences:: 88 passed; clippy clean
Gate: green
Deviation: pool scopes (PoolScope, PausedPoolScope) get no handle/deferred entry yet: they need a Send receiver; built with #988 when the lowering asks for them
Found: (1) task::scope … catch inside a fn main() without throws lowers to return Err(error) and fails in rustc (“mismatched types, expected () found Result”); probe: use std::task / fn main() { let r = task::scope fn(s) { s.spawn fn { f() }; 1 } catch { 0 } } with f throwing. (2) a detached async spawn of a scope leaks rustc warning “unused import: ProbePlain” into the program’s output.
Needs: #988 to test step 2 handles from Nikaia
Changelog: none
Owner: none
Disk freed: 0 (cache 5.4G, / 6.8G free; new entries over 100 MB: rlib/af187e66 285 MB, run-bundle/c1ccf85a 306 MB)
Rs2nika: none
Attribution:
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01GFeMqxRbtUMiGVyDMxsvEq
Pushed: local 6331c7abad3887e4a57375e1935f7148f30c429e