fibers B1.2: 0152 fixed → Atomic(bool) works; blocked on 0153 (re-export value-failable loses ! channel)
With 0151 + 0152 fixed, the async surface is callable and Atomic(bool) works.
Building the async examples isolated the TRUE remaining blocker (the earlier
'secondary or PHI' symptom, confirmed NOT an Atomic cascade): a re-exported
generic value-failable ($R, !E) fn loses its ! error channel at the call site
— the result types as a plain tuple, so await(...) or { ... } / try ...await()
fail / build a malformed i1 PHI. await/IoErr are re-exported via std.sx, so the
async surface hits it.
Narrowed to the generic + re-export co-requirement (non-generic re-export OK;
direct generic import OK). Filed issues/0153 with a minimal co-located 2-file
repro + a single-file stdlib-await repro + investigation prompt (root cause:
the monomorphized return-type's error-set, reached via the re-export alias,
resolves to a non-.error_set TypeId, so errorChannelOf misses the channel).
Per the STOP rule, paused B1.2's async examples pending the 0153 fix.
This commit is contained in:
@@ -4,11 +4,25 @@ Companion to [PLAN-FIBERS.md](PLAN-FIBERS.md). Update after every step (one step
|
||||
per the cadence rule). New corpus category: `18xx` concurrency.
|
||||
|
||||
## Last completed step
|
||||
**issue 0151 FIXED — generic `$T` now infers through generic-struct / pointer / UFCS-pack
|
||||
params.** `await`/`cancel`/`async` are CALLABLE again. The async SURFACE is now blocked on a
|
||||
DIFFERENT, freshly-exposed codegen bug: **issue 0152 — `Atomic(bool)` emits a sub-byte (i1)
|
||||
atomic that LLVM rejects** (the `Future.canceled: Atomic(bool)` field hits it). Suite green
|
||||
**728/0**, master clean.
|
||||
**issues 0151 + 0152 FIXED.** The async surface is CALLABLE and `Atomic(bool)` works. One LAST
|
||||
blocker remains, freshly isolated: **issue 0153 — a re-exported generic value-failable
|
||||
`($R, !E)` loses its `!` error channel at the call site** (typed as a plain tuple), so
|
||||
`await(...) or { … }` builds a malformed PHI. `await`/`IoErr` are re-exported via `std.sx`,
|
||||
so the async surface hits it. Suite green **729/0**, master clean.
|
||||
- **0152 fix (committed):** the atomic load/store emitters in `src/backend/llvm/ops.zig` now
|
||||
byte-promote a sub-byte (`bool`→`i1`) access to its `i8` storage type and `trunc`/`zext` the
|
||||
value at the boundary (new `atomicByteType` helper). rmw/cmpxchg left as-is (a `bool` rmw/CAS
|
||||
is rejected at the sx level — integer-only — so a sub-byte element never reaches them).
|
||||
Regression: `examples/1705-atomics-bool-byte-promoted.sx`. Issue 0152 marked RESOLVED.
|
||||
- **0153 filed (the remaining blocker):** generic + re-export is the co-requirement — a
|
||||
non-generic re-export keeps the channel, and a directly-imported generic value-failable keeps
|
||||
it; only the combination drops the `!`. Minimal co-located 2-file repro + a single-file
|
||||
stdlib-`await` repro + investigation prompt (root cause: the monomorphized return-type's
|
||||
error-set, reached via the re-export alias, resolves to a non-`.error_set` TypeId, so
|
||||
`errorChannelOf` no longer sees the failable channel). See `issues/0153-...`.
|
||||
|
||||
### Earlier — issue 0151 FIXED (committed `362674f`)
|
||||
Generic `$T` now infers through generic-struct / pointer / UFCS-pack params — details below.
|
||||
- **0151 fix (committed):** four gaps closed on the inference + UFCS-dispatch path —
|
||||
(1) `extractTypeParam`/`matchTypeParam(Static)` got a `parameterized_type_expr` arm
|
||||
(recover the arg instance's recorded per-param bindings via `struct_instance_bindings` +
|
||||
@@ -101,26 +115,28 @@ body); closed + locked. The review's `.naked`-lambda CRITICAL was a false positi
|
||||
(unparseable — `isLambda` breaks on the `abi` keyword).
|
||||
|
||||
## Current state
|
||||
**B1.2 Io capability is LANDED; the async surface is now CALLABLE but blocked on issue 0152.**
|
||||
Master GREEN (728/0), installed `sx` clean.
|
||||
- **0151 fixed (this session, committed):** the generic-inference engine now binds `$T`
|
||||
through a generic-struct param head (`Box($T)`), through a pointer (`*Box($T)`, incl. the
|
||||
UFCS auto-address-of receiver), and through a closure-return-via-pack on the UFCS dot-call
|
||||
path. So `async`/`await`/`cancel` in `library/modules/std/io.sx` — all `ufcs`, with
|
||||
`await`/`cancel` taking `*Future($R)` — are callable in every form. Details in the
|
||||
"Last completed step" block above; regression tests `examples/0214` + `0215`.
|
||||
- **NEW blocker — issue 0152 (`Atomic(bool)` → sub-byte i1 atomic):** with the surface
|
||||
callable, building the async examples now trips LLVM verification: `Atomic($T)` lowers a
|
||||
`bool` element to `i1` and emits an `i1` atomic load/store, which LLVM rejects ("atomic
|
||||
memory access' size must be byte-sized"). `Future.canceled: Atomic(bool)` hits this in
|
||||
`async`/`cancel`/`await`. Standalone repro + investigation prompt filed at
|
||||
`issues/0152-atomic-bool-sub-byte-atomic-llvm-reject.md`. The fix is codegen-level
|
||||
(`src/backend/llvm/ops.zig` atomic emitters — promote sub-byte atomics to `i8` storage with
|
||||
`trunc`/`zext` at the value boundary). A secondary `or`-merge PHI i1/i64 mismatch appeared in
|
||||
the same probe — likely entangled with the malformed `Atomic(bool)` field; re-check after 0152.
|
||||
**B1.2 Io capability LANDED; async surface CALLABLE + `Atomic(bool)` works; ONE blocker left
|
||||
(issue 0153).** Master GREEN (729/0), installed `sx` clean. Three of the four B1.2 surface bugs
|
||||
are now closed:
|
||||
- **0151 fixed + committed** (`362674f`): generic `$T` infers through generic-struct / pointer
|
||||
/ UFCS-pack params. `async`/`await`/`cancel` dispatch correctly. Regression `0214` + `0215`.
|
||||
- **0152 fixed + committed**: `Atomic(bool)` load/store byte-promoted to `i8` in the codegen
|
||||
emitters. `Future.canceled: Atomic(bool)` works. Regression `1705`.
|
||||
- **0153 (the remaining blocker, filed):** a re-exported generic value-failable `($R, !E)`
|
||||
loses its `!` channel at the call site (plain tuple), so `await(...) or { … }` / `try …await()`
|
||||
reject it / build a malformed `i1` PHI. `await`/`IoErr` are re-exported via `std.sx`, so the
|
||||
async examples hit it. The earlier "secondary `or` PHI" symptom was THIS, not an `Atomic`
|
||||
cascade (it persists after 0152). Minimal co-located repro + investigation prompt at
|
||||
`issues/0153-reexport-generic-value-failable-loses-error-channel.{md,sx}`. Root cause: the
|
||||
monomorphized return-type's error-set, reached via the re-export alias, resolves to a
|
||||
non-`.error_set` TypeId, so `errorChannelOf` (`lower/error.zig:148`) no longer sees the channel.
|
||||
- Issue **0150** (`void` struct field → SIGTRAP) remains DEFERRED — only `Future(void)` /
|
||||
`timeout`, which are B1.4.
|
||||
|
||||
Verified live (with all three patches in tree, before reverting nothing — 0151/0152 are
|
||||
committed, 0153 outstanding): `async`/`await` dispatch + build correct Futures; the ONLY failure
|
||||
is the lost `!` channel from 0153. A working dispatch probe is at `.sx-tmp/async_surface.sx`.
|
||||
|
||||
### B1.2 Io capability — what is LANDED + verified (commit 45d869d)
|
||||
- `Io :: protocol #inline { spawn_raw; suspend_raw -> !; ready; poll; now_ms; arm_timer; }`
|
||||
in `core.sx` next to `Allocator`, with `SpawnOpts{ pin: PinTarget }` + `ParkToken{ handle }`.
|
||||
@@ -178,17 +194,17 @@ fibers/Io/scheduler code yet. Grounded floor facts:
|
||||
boundary; a sharper sx diagnostic for it is a candidate polish, not a blocker.
|
||||
|
||||
## Next step
|
||||
**BLOCKED on issue 0152 (`Atomic(bool)` sub-byte atomic).** Once it lands, complete B1.2's
|
||||
async surface:
|
||||
**BLOCKED on issue 0153 (re-exported generic value-failable loses its `!` channel).** It is the
|
||||
LAST B1.2 surface blocker — 0151 + 0152 are fixed. Once 0153 lands, complete B1.2's async
|
||||
surface:
|
||||
1. **Add the async examples:** `examples/1805-concurrency-io-blocking-async.sx`
|
||||
(`context.io.async((a:i64,b:i64)->i64 => a+b, 40, 2).await() or {…}` → 42; `double:`/`sum:`)
|
||||
+ `1806-...-io-cancel.sx` (cancel → `await` raises `.Canceled`). The async surface is already
|
||||
callable (0151 fixed); a working probe lives at `.sx-tmp/async_surface.sx` — it builds the
|
||||
Futures and dispatches `async`/`await`/`cancel` correctly, only the `Atomic(bool)` codegen
|
||||
(0152) stops it. lock→green, then regen `.ir` (confirm layout-only).
|
||||
- Note: `await` returns a value-failable `($R, !IoErr)`; use `f.await() or { default }` (a
|
||||
braced `or`, not `catch <expr>`). Re-verify the `or`-merge PHI i1/i64 symptom is gone once
|
||||
0152 lands (it was likely a cascade from the malformed `Atomic(bool)` field).
|
||||
callable + `Atomic(bool)` works; a working dispatch probe lives at `.sx-tmp/async_surface.sx`
|
||||
— it builds the Futures and dispatches `async`/`await`/`cancel` correctly; ONLY the lost `!`
|
||||
channel (0153) on `await(...) or { … }` stops it. lock→green, then regen `.ir` (layout-only).
|
||||
- `await` returns a value-failable `($R, !IoErr)`; use `f.await() or { default }` (a braced
|
||||
`or`, not `catch <expr>`).
|
||||
2. Then B1.2 is truly done → proceed to **B1.3 (fiber runtime)**.
|
||||
|
||||
**Deferred (do NOT block B1.2 on these):** issue **0150** (`void` struct field SIGTRAP) — only
|
||||
@@ -200,10 +216,14 @@ done, inference incomplete); a dedicated effort; lambda workers are the B1.2 idi
|
||||
`call.zig:1229`, io last). Io protocol + materializers + push-inherit are LANDED + reviewed.
|
||||
|
||||
## Known issues / capability gaps
|
||||
- **🔴 B1.2 BLOCKER — issue 0152** (`Atomic(bool)` → sub-byte i1 atomic load/store; LLVM
|
||||
rejects "atomic memory access' size must be byte-sized"). Blocks the async examples via
|
||||
`Future.canceled: Atomic(bool)`. Standalone repro + fix prompt: `issues/0152-...`. Codegen-
|
||||
level (`src/backend/llvm/ops.zig` atomic emitters; promote sub-byte → i8 storage).
|
||||
- **🔴 B1.2 BLOCKER — issue 0153** (re-exported generic value-failable `($R, !E)` loses its `!`
|
||||
channel; the call result types as a plain tuple, so `await(...) or { … }` / `try …await()`
|
||||
fail / build a malformed i1 PHI). `await`/`IoErr` re-exported via `std.sx` hit it. Co-located
|
||||
repro + fix prompt: `issues/0153-...`. Root cause: the monomorphized return-type's error-set,
|
||||
reached via the re-export alias, resolves to a non-`.error_set` TypeId (so `errorChannelOf`
|
||||
misses it). The LAST B1.2 surface blocker.
|
||||
- **✅ issue 0152 — FIXED this session** (`Atomic(bool)` sub-byte i1 atomic → byte-promoted to i8
|
||||
in the load/store emitters). Regression: `examples/1705`. Unblocked `Future.canceled`.
|
||||
- **✅ issue 0151 — FIXED this session** (generic `$T` through generic-struct / pointer /
|
||||
UFCS-pack params). Regression: `examples/0214` + `0215`. Was the original B1.2 surface blocker.
|
||||
- **issue 0150** (deferred) — a `void` struct field crashes the compiler (unsized-type SIGTRAP
|
||||
@@ -319,3 +339,18 @@ done, inference incomplete); a dedicated effort; lambda workers are the B1.2 idi
|
||||
i1 atomic, LLVM reject; `Future.canceled` hits it). Filed with standalone repro + fix prompt.
|
||||
Per the STOP rule: shipped the 0151 fix, filed 0152, STOPPED. Resume the async examples
|
||||
(1805/1806) after 0152.
|
||||
- **0152 FIXED** — the atomic load/store emitters (`src/backend/llvm/ops.zig`) byte-promote a
|
||||
sub-byte (`bool`→`i1`) access to its `i8` storage type and `trunc`/`zext` the value at the
|
||||
boundary (new `atomicByteType` helper). rmw/cmpxchg left as-is (a `bool` rmw/CAS is rejected
|
||||
at the sx level — integer-only — so a sub-byte element never reaches them; comments record
|
||||
this). Regression `examples/1705-atomics-bool-byte-promoted.sx` (load/store round-trip). Issue
|
||||
0152 marked RESOLVED. Suite green 729/0. With `Atomic(bool)` working, the async surface
|
||||
exposed the TRUE remaining blocker — **issue 0153**: a re-exported generic value-failable
|
||||
`($R, !E)` loses its `!` channel at the call site (the earlier "secondary `or` PHI" symptom
|
||||
was this, NOT an `Atomic` cascade — confirmed it persists after 0152). Narrowed to the
|
||||
generic+re-export co-requirement (non-generic re-export OK; direct generic import OK; only the
|
||||
combination drops `!`). Root cause: the monomorphized return-type's error-set, reached via the
|
||||
re-export alias, resolves to a non-`.error_set` TypeId, so `errorChannelOf`
|
||||
(`lower/error.zig:148`) misses the channel. Filed `issues/0153-...` with a minimal co-located
|
||||
2-file repro + a single-file stdlib-`await` repro + investigation prompt. Per the STOP rule:
|
||||
shipped the 0152 fix, filed 0153, STOPPED. Resume the async examples after 0153.
|
||||
|
||||
Reference in New Issue
Block a user