[Task 111 defer] Cross-fn discharge propagation requires shared state — defer to Task 117#51
Merged
Merged
Conversation
… — defer to Task 117 follow-up Three implementation attempts on PR #50 (4dfdbc7 register-pair multi-return, 670f7a1 out-pointer + Variable, 5e2686e out-pointer + StackSlot) all failed identically with discharge-class shapes. A diagnostic eprintln commit (4086307) confirmed the bug is architectural, not implementation: the OLD LAST_TERMINAL_TAG/_VALUE TLS achieved cross-FN shared state implicitly because TLS is thread-global; per-fn / per-call mechanisms can't reproduce this. Diagnostic case (catch_example_recovers_with_42): DISCHARGED bypass: writing (42, tag=2) to risky's slot 0x...aac8 top-level terminal: writing (0, tag=0) to user-main's slot 0x...ab00 risky has Sync ABI (its body shape — let result = raise(...); result + input — doesn't match any Cps body classifier). risky's discharge writes its OWN slot. user-main's handle exit reads user-main's slot, never touched by risky. Result: handle takes DONE path with body_val = risky's normal-completion 49 instead of discharge value 42. Closure path (per [DEVIATION Task 111]): 1. Recommended: defer to Task 117 first-class-k follow-up. Task 117 modifies the same surface; co-shipping the lift uses whichever ABI Task 117 settles on, informed by Task 117's actual requirements rather than guessed in advance. 2. Alternative: thread through every fn ABI as an extra parameter — own multi-PR slice, comparable scope to Plan B' B.3 TypeExpr::Fn lift. Out of scope for Plan D. Plan B' carryover #1 status updates to deferred-with-revised- closure. The OLD TLS approach continues to work for all e2e tests; no user-visible surface is affected by this deferral. PR #50 closes without merge; the four Task 111 commits are preserved on the plan-d-task-111 branch for the diagnostic record. Stage 11 next: Task 112 (wrapper-fn-frame composition fix). EOF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defers Plan D Task 111 (TLS → packed multi-return for
sigil_run_loop). Plan B' carryover #1 stays open with revised closure scope.Why deferred
Three implementation attempts on PR #50 all failed identically. The bug is architectural, not implementation:
4dfdbc7[I64, I64]register-pair multi-return + Rust#[repr(C)] struct { u64, u64 }670f7a1Variableper-fn last-terminal vars5e2686eStackSlot(explicit memory ops)Diagnostic eprintln commit
4086307confirmed the cause. Forcatch_example_recovers_with_42:DISCHARGED bypass: writing (42, tag=2) to out=0x7ffc6c12aac8(inrisky's frame)top-level terminal: writing (0, tag=0) to out=0x7ffc6c12ab00(inuser-main's frame)The OLD TLS achieved cross-fn shared state implicitly because TLS is thread-global. Per-fn / per-call mechanisms scope the (value, tag) to the immediate caller; the discharge is invisible to the enclosing handle expression in a different stack frame. Specifically:
riskyhasUserFnAbi::Sync(body shape mismatch with all three Cps body classifiers), so its discharge writes its own slot, then risky's body continues sequentially (result = 42; result + input = 49) and returns 49 via Sync ABI; user-main's handle exit reads its own untouched slot.Closure path
*mut TerminalResultthrough every fn ABI as an extra parameter — own multi-PR architectural slice, comparable scope to Plan B' B.3TypeExpr::Fnlift. Out of Plan D scope unless explicitly authorized.Files changed
PLAN_D_DEVIATIONS.md— adds[DEVIATION Task 111](53 LOC)PLAN_D_PROGRESS.md— Task 111 status flips todeferredwith closure-path summaryNo code changes. PR #50 (the failed implementation attempts) closes without merge; its four commits are preserved on the
plan-d-task-111branch for the diagnostic record.Stage 11 next
Task 112 (wrapper-fn-frame composition fix). Stage 11 review checkpoint will close on Task 112 alone since Task 111 deferred.
Test plan
ubuntu-24.04(build + test, cold-checkout) — no code change so should pass cleanlymacos-14(build + test, cold-checkout)