Skip to content

Triage fixes: __le-across-yield (#97), break wording (#95), closure caching (#96), 5.5 vararg aliasing (#94)#106

Merged
ianm199 merged 9 commits into
mainfrom
triage-fixes-2026-06-01
Jun 1, 2026
Merged

Triage fixes: __le-across-yield (#97), break wording (#95), closure caching (#96), 5.5 vararg aliasing (#94)#106
ianm199 merged 9 commits into
mainfrom
triage-fixes-2026-06-01

Conversation

@ianm199
Copy link
Copy Markdown
Owner

@ianm199 ianm199 commented Jun 1, 2026

Triage pass over the freshly-opened issues: verified each against the current code + reference binaries for all 5 versions, then fixed the four well-scoped ones. Each fix verified vs the matching /tmp/lua-refs reference (5.1.5/5.2.4/5.3.6/5.4.7/5.5.0), the official tests, GC canaries, the 112-test multiversion oracle, and the full 5.4 parity sweep (36/44 — the 8 DIVERGE are the known PRNG/limit/locale/codegen set, unchanged).

Fixes

#97__le from __lt across a yield (5.1–5.4) fix(vm)
Re-introduced the CIST_LEQ mark (bit 13, as C). The synchronous derive in call_order_tm was already correct; the gap was finish_op not negating on resume after the __lt yielded. Was a silent wrong answer (inverted comparison). 5.5 correctly still raises (derivation removed).

#95break outside loop wording per version fix(parser)
Version-gated: 5.1 eager no loop to break, 5.2/5.3 deferred <break> at line N not inside a loop, 5.4 break outside loop at line N, 5.5 eager break outside loop near 'break'. Message text now matches reference on all 5. (Filed #105 for the separate, pervasive 5.1 special-token quoting gap — different root cause in the shared lexer.)

#96 — loop-built-closure == caching (5.2/5.3) fix(vm)
Added Proto.cache (C's getcached): OP_CLOSURE reuses the last closure built from a proto when upvalues are identical. Gated to 5.2/5.3 (issue said 5.3-only, but reference shows 5.2 caches too); inert on 5.4 (cache stays None).

#94 — 5.5 named-vararg ...t shared storage fix(vm)
... now unpacks live from the packed table t (count = its n field), so mutating t shows through a later ... (99 2 3, not 1 2 3). Adds Proto.vararg_table_reg, reconstructed during undump by scanning for OP_VARARGPACK so string.dump round-trips without diverging from C's bytecode layout. vararg.lua now passes on 5.5 (was the sole L111 failure).

Not in scope (architectural — documented, not driven-by)

Closes #97, #95, #96, #94.

ianm199 and others added 9 commits June 1, 2026 15:37
Re-introduce the CIST_LEQ mark (1<<13, as C) so a __lt metamethod standing in
for a missing __le negates correctly when it yields. The synchronous derive in
call_order_tm was already correct; the gap was finish_op not knowing to negate
on resume. Gated to 5.1-5.4 (5.5 dropped LUA_COMPAT_LT_LE). Verified vs
reference on all 5 versions; coroutine.lua/events.lua still MATCH.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.1 raises eagerly (no loop to break), 5.2/5.3 defer (<break> at line N not
inside a loop), 5.4 keeps (break outside loop at line N), 5.5 raises eagerly
(break outside loop near 'break'). Message text now matches reference on all
five versions; valid break-in-loop and errors.lua/goto.lua unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Proto.cache (C's getcached): OP_CLOSURE reuses the last closure built from
a proto when the new instantiation captures identical upvalues, so they compare
== on 5.2/5.3. Gated to those versions (5.1 never cached, 5.4/5.5 removed it),
so the 5.4 oracle is inert (cache stays None). Cache is traced to avoid
dangling; pins one closure per proto (bounded) vs C's GC-cleared weak cache.
NB: issue said 5.3-only but reference shows 5.2 caches too. Verified vs
reference on all 5 versions; closure/goto/gc/gengc/tracegc MATCH, GC canaries pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
function f(...t): ... now unpacks live from the packed table t (count = its n
field) instead of the frame's extra-arg slots, so mutating t shows through a
later ... (ref 99 2 3, not 1 2 3). Adds LuaProto.vararg_table_reg, set by the
parser at the VARARGPACK site and reconstructed during undump by scanning the
code for OP_VARARGPACK (so string.dump round-trips without diverging from C's
bytecode layout). Inert pre-5.5 (reg stays None -> frame path). vararg.lua now
passes on 5.5 (was the sole failure at L111); 5.4 oracle unchanged (36/44, the
8 DIVERGE are the known PRNG/limit/locale/codegen set).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9 oracle tests pinning this PR's fixes (le-across-yield negation, per-version
break wording, 5.2/5.3 closure caching, 5.5 named-vararg aliasing incl. dump
round-trip). All values captured from the reference binaries. 121 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The v0.0.23 Windows fix (#90) added cfg-gated localtime_r/localtime_s FFI
(documented, safe-fallback) but did not bump the ceiling, so the unsafe-budget
gate has been red on main for every PR since. Not new unsafe from this PR
(which doesn't touch lua-cli) — just reconciling the ceiling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ianm199 ianm199 merged commit 1023472 into main Jun 1, 2026
3 checks passed
@ianm199 ianm199 deleted the triage-fixes-2026-06-01 branch June 1, 2026 23:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vm/coroutine: __le-from-__lt derivation across a yield (verify current state)

1 participant