Repository navigation
rc: a kept bound method counts the object it is bound to - #640
Merged
Merged
Conversation
`let m = v.get; v = mkv(2); m()` ran on a freed object under rc, and so did a bound method kept in a field or an element. A bound method's value carried a null type tag at CLOSURE_TYPE_INDEX, so its receivers' retains and releases did nothing for `this`. Under rc the lowering now gives a method bound to a class object that class's tag, as an interface over the object gets its tag: a bound value is born with no count, and each receiver that keeps it counts the object. ThisSymbolRef / ThisVirtualSymbolRef cast `this` to an opaque pointer, so they record the object's type on the CreateBoundFunction they build (BOUND_OBJECT_TYPE_ATTR_NAME). own, gc and none keep the null tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Two follow-up notes from checks after opening:
|
ASDAlexander77
added a commit
that referenced
this pull request
Oct 22, 2026
…count (#642) `const m = h.v.get` and `const i: I = h.v` were folded into the view itself, holding no reference of their own, so `h.v = d` freed the object `m()` and `i.get()` then ran on (a crash under rc; `let m = h.v.get` was fine). #637 gave such a const storage when its object is read out of a local's slot, and #640 made a kept bound method count its object; a view over a field read was left out. Under rc it now gets storage like a `let`, as a const read out of a field already does (#635). Under own the folded read stays a borrow. 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.
Under rc,
let v = mkv(1); let m = v.get; v = mkv(2); m()ran on a freed object and printed 1003/1004, where gc prints 3. A bound method kept in a field (h.f = v.get) or in an element ([v.get]) failed the same way. Receivers already retain and release bound values through the tag atCLOSURE_TYPE_INDEX, but a bound method carried a null tag there, so keeping it counted nothing.Fix (LowerToLLVM)
INTERFACE_TYPE_INDEX.ThisSymbolRefandThisVirtualSymbolRefcastthisto an opaque pointer before building theCreateBoundFunction. So they record the object's type on it in a new attribute,BOUND_OBJECT_TYPE_ATTR_NAME(Defines.h).Still open:
const m = h.v.get, a const bound method over a field read, is folded and holds nothing. That's the const-folding side and is not changed here. #637 covers the const over a local.Tests
tests/00bound_method_count.ts(default + rc/none corpus): a bound method in alet, in a field, in an element.Results
ctest -C Release, 4886/4886 passed🤖 Generated with Claude Code