fibers B1.0a: close generic/pack is_pure gap (review)

Adversarial review of dd363ca found is_pure was set only at the two
declareFunction decl sites. Generic monomorphization (generic.zig) and
pack expansion (pack.zig) create the IR Function via a different path
and left is_pure false, so a generic abi(.pure) instance bypassed the
emit bail and silently shipped a framed body — it returned 42 but
leaked the prologue's stack adjustment (the exact SP-in != SP-out
corruption the lock exists to prevent).

Both paths now set is_pure and route .pure bodies through the asm-only
+ unreachable cap, mirroring the decl path. Locked by
examples/1801-concurrency-pure-generic-bail.sx (generic .pure reaches
the loud bail).

The review's other CRITICAL (a .pure lambda) is a false positive:
isLambda's return-type scan (parser.zig:3652) breaks on the abi
keyword, so a .pure lambda is unparseable and parseLambda's abi
handling is never reached. Latent isLambda/parseLambda inconsistency,
not a B1 concern.

Suite green (723/0).
This commit is contained in:
agra
2026-06-20 14:45:29 +03:00
parent dd363ca877
commit 40424df1b8
8 changed files with 65 additions and 6 deletions

View File

@@ -0,0 +1,23 @@
// Stream B1 (fibers) step B1.0a — regression for an adversarial-review finding.
//
// `abi(.pure)` on a GENERIC function is monomorphized through a different
// Function-creation path (lower/generic.zig) than a plain decl, and originally
// that path left `is_pure` unset — so the emit bail never fired and a framed
// body shipped (it "returned 42" but leaked the prologue's stack adjustment:
// the exact silent corruption the lock exists to prevent). This example pins
// the now-correct behavior: a `.pure` generic instance reaches the loud emit
// bail (build-gating, nonzero exit) just like a plain `.pure` decl. The sibling
// pack-expansion path (lower/pack.zig) was hardened the same way. Host-
// independent (the bail fires before instruction selection), so no `.build`
// pin. B1.0b will turn the plain-decl form (1800) green; this generic case
// stays a bail-lock (a naked generic is exotic and out of B1's scope).
answer :: ($T: Type) -> i64 abi(.pure) {
asm volatile {
#string A
mov x0, #42
ret
A
};
}
main :: () -> i64 { return answer(i64); }

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1 @@
error: `abi(.pure)` function 'answer__i64' LLVM emission not yet implemented

View File

@@ -0,0 +1 @@