Skip to content

A const interface or bound method made over a local holds what it shows - #637

Merged
ASDAlexander77 merged 2 commits into
mainfrom
fix-const-view-of-local
Oct 22, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
fix-const-view-of-local

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

let v = mkv(1); const i: I = v; v = mkv(2); i.w.x read freed memory under rc and own, and so did const m = v.get; v = mkv(2); m(). A const of an interface view, or of a bound method, made over a read of a local's slot was folded. It was a view with no reference of its own, so the assignment freed the object it still showed. The let forms were already right for the interface.

Fix: processConstRef (MLIRGenImpl.h) gives such a const storage like a let, as #454 did for a const read straight out of a local's slot. The new viewsLocalSlot looks through NewInterface, ThisSymbolRef, ThisVirtualSymbolRef and CreateBoundFunction to a read of an owning local.

Effect per model

  • Interface: counted under rc and owned under own. Both now print the right value.
  • Bound method under own: now rejected with "takes a second reference", the same as let m = v.get. Before, it was accepted and printed 1002 instead of 3.
  • Bound method under rc: still broken. A bound method is not counted under rc, because its this carries a null tag (MLIRTypeHelper ownsHeapMemory). So const m = v.get is now exactly as broken as let m = v.get already was. Counting bound methods under rc is a separate change to the lowering.

Tests

  • tests/00const_interface_of_local.ts: default, rc/none corpus, and own (JIT + AOT).
  • Negative own_err_const_bound_method_reassigned.
  • Teeth: with the change switched off, the rc corpus test, the own run and the negative fail.

Results

  • Windows: ctest -C Release, 4865/4865 passed
  • WSL (Linux): 4847/4847 passed

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits October 22, 2026 16:32
`const i: I = v` and `const m = v.get` were folded: a view of a read of
`v`'s slot with no reference of its own, so `v = mkv(2)` freed the object
`i` and `m` still used (rc and own). Like a const read straight out of a
local's slot (#454), such a const now gets storage like a `let`.

An interface is then counted under rc and owned under own. A bound
method is still not counted under rc (its `this` carries a null tag), so
`const m = v.get` stays broken there, as `let m = v.get` is; under own it
is now rejected, as the `let` is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	tslang/lib/TypeScript/MLIRGenImpl.h
@ASDAlexander77
ASDAlexander77 merged commit ce72025 into main Oct 22, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-const-view-of-local branch October 22, 2026 16:40
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant