-
Notifications
You must be signed in to change notification settings - Fork 0
feat(d5.4): alias_join primitive + per-RID T4 wrap/adopt (step 1) #133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,6 +105,7 @@ | |
|
|
||
| from .ast_nodes import ( | ||
| Acquire, | ||
| AliasJoin, | ||
| Call, | ||
| Effect, | ||
| EffectParam, | ||
|
|
@@ -1539,6 +1540,33 @@ def _lower_flow(nodes: list[Any], ffile: str, fname: str, | |
| # partial-path leak reads as a "pooled buffer", not "disposable". | ||
| "pool": n.get("kind") == "pool"} | ||
| body.append(Let(handle, Acquire("Disposable", [], line), line)) | ||
| elif op == "alias_join": | ||
| # P-005 D5.4 (T4 wrap/adopt): `var` is a new owning handle on the SAME | ||
| # resource obligation as `src` — a factory returning a wrapper of `src`, | ||
| # or a ctor adopting `src` into an owning field (T4a ≡ T4b). The result | ||
| # joins `src`'s alias set: dropping the wrapper while `src` is released is | ||
| # NOT a leak, releasing both is OWN003, using either after release is | ||
| # OWN002 — all evaluated per-RID by the core. Emitted only when `src` is a | ||
| # tracked local; an unknown `src` makes no claim (precision-first). | ||
| name = str(n.get("var", "?")) | ||
| src_h = localmap.get(str(n.get("src", ""))) | ||
| # Overwriting a tracked local KILLS its previous ownership binding — the | ||
| # same rule as a call-result overwrite (D5.2). Drop the stale mapping FIRST, | ||
| # even when the new alias's `src` is untracked: we make no claim on the new | ||
| # handle, but the OLD obligation must not be silently discharged by a later | ||
| # `release name` resolving to the dead handle (Codex P2). It leaks instead. | ||
| # A hoisted local keeps its single outer-scope handle (declared once). | ||
| if name not in hoisted: | ||
| localmap.pop(name, None) | ||
| if src_h is not None and name not in hoisted: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an Useful? React with 👍 / 👎. |
||
| handle = f"loc_{loc[0]}" | ||
| loc[0] += 1 | ||
| localmap[name] = handle | ||
| handles[handle] = {"file": ffile, "line": line, "event": name, | ||
| "component": fname, "resource": "flow-local", | ||
| "ever_released": name in released_vars, | ||
| "pool": False} | ||
| body.append(AliasJoin(handle, src_h, line)) | ||
| elif op == "use": | ||
| h = localmap.get(str(n.get("var"))) | ||
| if h is not None: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this maps the new handle onto
src's RID, active loans are still recorded and queried by the original handle id (Loan.owner/loans_on), not by RID. That meansalias_join w inner; borrow inner as b { release w; }is accepted even though releasing another owning alias of the borrowed resource should be OWN008, and the same gap applies to mutable-borrow/use checks through the other alias. The loan owner needs to resolve through the shared RID once aliases exist.Useful? React with 👍 / 👎.