Skip to content

fix(#92): may-share on field/index stores + clique closure on bridge rebind (E3003 / O5.2) - #220

Closed
zidirahim617-del wants to merge 1 commit into
limitlessprojects:mainfrom
zidirahim617-del:fix/92-may-share-field-index
Closed

zidirahim617-del wants to merge 1 commit into
limitlessprojects:mainfrom
zidirahim617-del:fix/92-may-share-field-index

Conversation

@zidirahim617-del

Copy link
Copy Markdown
Contributor

Summary

Closes #92 — the two live sub-bugs of the may-share maintenance report (the third shape, projections/slices/calls inside composite literals, is already rejected on current main by the collect_ref_roots generalization from #160 / corpus 40).

Sub-bug 1 — field/index stores record no may-share edge. process_assign only called record_may_share for bare PlaceKind::Ident rebind targets. h.m = m / xs[0] = m / mm["a"] = m therefore left the base binding unedged, while the composite-literal twin h := holder{m: m} recorded the edge and rejected with E3003. A later task worker(move m, done) froze nothing and main kept writing through the moved map header.

Sub-bug 2 — bridge rebind severs transitive sharing. h2 := h1; h3 := h2 is the 2-hop chain h1—h2—h3. Rebinding the bridge (h2 = holder{m: ...fresh...}) called share_clear("h2"), which deleted h2's incident edges without connecting its former peers — h1.m and h3.m are still the same map header, but the graph forgot it.

Fix

  1. loans.rs::process_assign — for every non-Ident assign target, record may-share from the place's root binding to the value's ref roots, exactly like the Ident twin already does.
  2. model.rs::share_clear — vertex elimination now closes the component: former peers link pairwise (clique closure). A bridge whose only peer is the moved root creates no closure pair, so a genuine fresh rebind never over-freezes.

Evidence (pre-fix → post-fix on this branch)

program hyb check before go run hyb check after
43-may-share-field-store (h.m = m) OK (0 diagnostics) fatal error: concurrent map writes HYB-E3003 (A1b) at h.m["k"] = i
44-may-share-bridge-rebind (h2 = fresh bridge) OK (0 diagnostics) fatal error: concurrent map writes HYB-E3003 (A1b) at h3.m["k"] = i
projection-in-literal (h2 := holder{m: h1.m}) already rejected on main — unchanged (corpus 40 family)
accept control: fresh rebind of a single-peer bridge + write through it OK runs clean OK (0 diagnostics) — no over-freeze

Verification

  • cargo test -p hy-check: 205/0 (all suites, including call_share, param_share_move, closure_alias_move, const_write)
  • corpus harness: 44/44 (rows 43, 44 added; all 42 prior rows unchanged, tripwire not fired)
  • differential reject-side: 29/29 (accept-side 11/13 — the two failures are rows 12/13 needing runtime/cgo, which fails standalone on this machine with "C compiler not found" without this patch applied; environment, not regression)
  • over-freeze guard (written and run on this branch): rebinding an intermediate whose only peer is the moved root stays accepted, and the clique-closure chain (h1—h2—h3, rebind h2) correctly freezes h3 on move h1

Payout note

Soundness class (accepted-but-unsound programs at the task boundary), reproduced before the fix, merged-ready with corpus registry rows — per BOUNTY.md Track #5. Reporter/fixer: @zidirahim617-del.

Fixes #92

… close the component under bridge rebind (clique closure)

Two live sub-bugs of issue limitlessprojects#92 (field-store asymmetry + share_clear severing):

1. process_assign only recorded may-share for bare Ident rebind targets, so
   `h.m = m` / `xs[0] = m` / `mm["a"] = m` left the base binding unedged while
   the composite-literal twin `h := holder{m: m}` rejected — a later move of
   the value froze nothing and main kept writing through the moved map header
   (hyb check OK(0) / go run fatal: concurrent map writes). The fix records
   may-share from the place root to the value ref-roots on every non-Ident
   assign target, exactly like the Ident twin.

2. share_clear deleted a rebound bridge's incident edges without connecting
   its former peers, severing transitive paths (`h2 := h1; h3 := h2;
   h2 = fresh` orphaned h3 from h1 although h1.m and h3.m are the same map
   header). Vertex elimination now closes the component: former peers link
   pairwise (clique closure). A bridge whose only peer is the moved root
   creates no closure pair, so a genuine fresh rebind never over-freezes
   (accept-side guard: corpus 44's rebind-isolated control + hy-check unit
   suites + corpus 42/42 unchanged rows).

The third reported shape (projection/slice/call inside a composite literal)
is already rejected on current main by the collect_ref_roots generalization
(limitlessprojects#160 / corpus 40); this PR pins the two live omissions.

corpus 42 -> 44 (rows 43 = field store REJECT A1b, 44 = bridge rebind
REJECT A1b, both HYB-E3003 / O5.2), VERDICTS.md distribution 44 programs.
Verified: hy-check 205/0, corpus harness 44/44, differential reject-side
29/29 (accept-side 11/13 — the two failures are the missing local C
toolchain for runtime/cgo rows 12/13, reproduced standalone without this
patch), over-freeze accept control (fresh rebind + write through it)
stays OK (0 diagnostics).

Fixes limitlessprojects#92
@limitlessprojects

Copy link
Copy Markdown
Owner

Triage (2026-10-15, AI maintainer, post-CI-repair): may-share on field/index stores + clique closure on bridge rebind (issue #92) — the field-ASSIGN half overlaps pr-162's generalized collector (literals are walked now), so hole-by-hole verification decides what remains live; the bridge-rebind clique closure half looks untouched by anything landed. Queued in the checker conveyor. No action needed from you.

@zidirahim617-del

Copy link
Copy Markdown
Contributor Author

This PR (#220, head fix/92-may-share-field-index) is now superseded — I rebased onto current main and confirmed another open PR (fix/may-share-field-assign-literal-bridge, #93) already covers #92 with the field/index-store may-share + literal-projection tracking.

Repro for the original #92 family now rejects cleanly on main:

error[HYB-E3003]: write through a live alias of a moved value

Closing this one to avoid a duplicate. The still-open and still-unfixed issue I am actively working is #98 (PR #223, rebased and green on current main: workspace green, corpus 42/42, differential reject-side 29/29).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants