Repository navigation
-mm=own: a read of a global ends at a call that may assign the global - #661
Merged
Merged
Conversation
`const c = G; reset(); print(c.x)`, where `reset` does `G = new V(1)`: the read borrows what `G` holds, and the call frees it while `c` still reads it. own accepted it and read freed memory (exit 139), also when the assignment is a call further down (`step()` calling `reset()`). checkGlobalRead (#655) ended such a read only at a store to the global in the same function; follow-up 11. OwnershipSignaturePass pins on each call the globals it may give a new value (pinAssignedGlobals): a store to the global, or its release, in a callee or in a call it makes, to a fixpoint; a call that may drop and whose callees are not known may assign any, one that drops nothing assigns none. checkGlobalRead counts such a call among the read's ends. A read handed to that call as an argument stays #639's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 23, 2026
ASDAlexander77
added a commit
that referenced
this pull request
Oct 23, 2026
…n that global (#678) #639 refused any call that might drop anything once a value read out of an assigned global was lent to it, though only a store to the global releases its block: `G = new N(2); other(G)`, where other assigns H, was rejected. The check now reads what pinAssignedGlobals (#661) put on the call, which runs before it: it refuses a call that may assign that global, or one it cannot name (an indirect call, a callee calling one), and lends to any other. A callee that assigns the global itself, through another function, a method or a function value is still refused. own_err_global_kept_field is now refused by checkGlobalRead, which it was written for: `keep` stores the lent value into a field that outlives the next assignment of `g`; its pinned message follows. Tests: own_global_argument_other_global under every model, own_err_global_argument_indirect. Own corpus unchanged (533). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Follow-up 11 from the own-raytrace rulings ("own accepts a callee that assigns a global after the caller took a
constread of it").Bug
const c = G; reset(); print(c.x)withreset() { G = new V(1); }: the read borrows whatGholds and the call frees it whilecstill reads it. own accepted it and read freed memory (exit 139 on current main), also through a further call (step()callingreset()).checkGlobalRead(#655) ended such a read only at a store to the global in the same function.Fix
OwnershipSignaturePass::pinAssignedGlobals(aftercomputeDrops): the globals each function may give a new value - a store to the global or its release in its body, or in a call it makes, to a fixpoint - pinned on each call as__own_assigns_globals(names). A call that may drop and whose callees are not known gets__own_assigns_any_global; one that drops nothing (callMayDropfalse: imported,.instanceOf, no-drop callees) gets nothing.checkGlobalReadcounts such a call among the read's ends, beside same-function stores, so the existing "'c' borrows 'G' but is used here after 'G' is released or overwritten" fires, with the note at the call. A read handed to that call as an argument stays A global lent to a call that assigns it: rc holds a count, own rejects #639's.Tests
own_err_global_read_callee_assigns,..._transitive.own/own_global_read_callee_other.tsunder own, rc, none, gc: calls that assign only another global, or none, stay accepted and correct.Verified
MALLOC_PERTURB_=165 MALLOC_CHECK_=3: 8/8.🤖 Generated with Claude Code