Repository navigation
rc: a const read out of a field keeps a count of its own - #635
Merged
Merged
Conversation
`const c = h.c` was folded into the read itself, holding no reference, so `h.c = d` freed the block `c` still read (and a `return` through `finally` read it after the field's overwrite). Under rc such a const now gets storage like a `let`, as a const read out of a local's slot already does (#454). Under own the folded read stays a borrow, rejected when used after the overwrite. Element reads are not covered yet: a destructuring past the end of an array reads whatever follows its data, and a count taken of that faults, as it does for a `let` today (00array_rest_copy). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 22, 2026
ASDAlexander77
added a commit
that referenced
this pull request
Oct 22, 2026
`const c = arr[0]` (and `const [c] = arr`) was folded into the read itself, holding no reference, so `arr[0] = d` freed the block `c` still read. Under rc such a const now gets storage like a `let`, as a const read out of a field already does (#635). That needed an out-of-bounds destructuring fixed first: `const [a, b, c] = pair` read whatever followed the array's data. Under rc a count taken of it faulted (for a `let` too), and under gc/none it was undefined behaviour that LLVM used - `print(c == null)` after it made main print nothing at all. An element past the end of an array is now the default of its type: null for a reference (TS has undefined there), 0 for a number. A runtime array checks its length; a const array literal's size is known, so no read is emitted. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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
-mm=rc,const c = h.c; h.c = new C(9); print(c.x)read a freed block. Aconstwas folded into the field read itself and held no reference, so the overwrite freed whatcstill read. The same happened when areturninsidetrywent through afinallythat read the const after the field was overwritten.Fix: under rc, a
constwhose initializer is a read out of a field (through casts) now gets storage like alet, the same treatment #454 gave a const read out of a local's slot (processConstRef, MLIRGenImpl.h). Under own the folded read stays a borrow, which own already rejects when it is used after the overwrite. own IR and gc/none output don't change.Not covered yet: element reads (
const c = arr[0]). A destructuring past the end of an array (const [a, b, c] = pair, in00array_rest_copy) reads whatever follows the array's data. A count taken of that faults, and it already does today for aletunder rc. Element reads need that out-of-bounds read fixed first.Test:
tests/00const_field_read.tscovers a field, a nullable field, and a read infinallyafter the overwrite. It runs as a default test and in the rc/none corpus. Teeth: with the new clause switched off,test-compile-rc-corpus-00const-field-readfails.ctest -C Release, 4862/4862 passed🤖 Generated with Claude Code