fix(#6640): take heap blocks only through the releasing scope - #6668
fix(#6640): take heap blocks only through the releasing scope#6668yangjj-iso wants to merge 1 commit into
Conversation
…cope Resolves the objectionary#6507 puzzle in Heaps. The two-argument malloc handed out a block with nobody responsible for releasing it, and free let any caller release a block it did not own, so the scoped malloc was a convention rather than a rule. Both are private now, which makes the scope the only way in and out. The seven HeapsTest cases that took a block raw and freed it by hand moved onto the scoped form, the two EOmallocEOofTest probes now ask size whether the block survived instead of trying to free it a second time, and failsOnClearingEmptyBlock is gone because no caller can reach free. The private pair sits at the end of the class: qulice orders methods by visibility, and leaving malloc where it was put every package-private method after it out of order. Closes objectionary#6640
|
🚀 Performance AnalysisAll benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information. Click to see the detailed report
✅ Performance gain: |
There was a problem hiding this comment.
Pull request overview
This PR enforces scope-based ownership for heap blocks in eo-runtime by removing external access to raw allocation/free APIs, ensuring blocks can only be acquired through a releasing scope and making misuse (double-free / freeing чужой block) impossible by construction.
Changes:
- Made raw
malloc(phi, size)andfree(id)private inHeaps, leavingmalloc(phi, size, scope)as the only allocation/release path. - Refactored
HeapsTestcases to allocate blocks through the scopedmalloc, removing manualfreecalls and deleting the now-unreachablefailsOnClearingEmptyBlock. - Updated
EOmallocEOofTestto verify release viaHeaps.size(id)(expecting failure) instead of probing with a secondfree.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| eo-runtime/src/main/java/org/eolang/Heaps.java | Removes the puzzle/todo and makes raw allocation/free private to enforce scope-only heap ownership. |
| eo-runtime/src/test/java/org/eolang/HeapsTest.java | Moves tests to scoped allocation, removes manual frees, and drops an unreachable free-on-empty test. |
| eo-runtime/src/test/java/org/eolang/EOmallocEOofTest.java | Switches “freed?” probes from free to size to avoid relying on now-private APIs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
The failure is a Saxon error inside Everything else is green, including the two checks that matter most for this change and that I could not complete locally on Windows: qulice and mvn (macos-15, 26). |
|
Fair — I was explaining the red, not asking you to look past it. A broken master is the reason not to merge, not a reason to merge anyway. So I went after the break instead: #6672 fixes #6669. The template at I will rebase this branch onto a green master once that lands, rather than ask for anything here in the meantime. |
|
Moving this to a draft while master is red. The post is explicit that you wait, and leaving it open asks for review time the build has not earned yet. Sweeping every job rather than just the one I had looked at turned up two more reds on master, both now reported:
So #6672 on its own will not turn master green. I said otherwise earlier in this thread and that was too quick — I had checked the I will mark this ready again once master is green, rebased onto it. |
|
@yangjj-iso try to sync with master, it should work now |



@yegor256 — this resolves the
6507-93ee2a46puzzle inHeaps.Closes #6640
What the puzzle asked for
Four steps, and they only work together:
freecannot become private until nothing outside the class calls it, so the test moves and the visibility change have to land in one commit.HeapsTestmoved onto the scopedmalloc;EOmallocEOofTestmoved offfree;mallocandfreeare private;failsOnClearingEmptyBlockis gone.What changed
Heaps. The two-argumentmallochanded out a block with nobody responsible for releasing it, andfreelet any caller release a block it did not own — somalloc(phi, size, scope)was a convention rather than a rule. Both are private now, which makes the scope the only way in and out. Nothing insrc/mainwas affected:EOmalloc$EOofalready goes through the scoped form, and it was the only production caller.HeapsTest. Seven cases took a block raw and freed it by hand; they now run inside the scope. Two of them got shorter —returnsValidSizeis a one-liner againstHeaps.INSTANCE::size— and the ones that assert on an exception mid-scope keep the assertion inside the lambda so the block is still allocated when it runs.failsOnClearingEmptyBlockis deleted rather than adapted, because "freeing an unallocated block fails" is no longer a reachable state.EOmallocEOofTest. Both probes asked "is it freed?" by callingfreea second time and expecting a throw. They now asksizeinstead, which throws the sameExFailurefor an unallocated block, so the assertion type is unchanged and the probe no longer needs a private method.On the size of this one
185 hits, over the 40–100 the guidelines ask for, and I could not find an honest way to split it.
Roughly 56 of those are mechanical: qulice orders methods by visibility, so leaving
mallocwhere it was reportedMethodsOrderCheckagainst every package-private method below it. Moving the private pair to the end of the class fixes that but counts as a delete plus an add of the same body. The remaining change is the seven test conversions, which cannot be separated from the visibility change without leaving the tree uncompilable in between. Happy to reshape it if you would rather have it another way.Verification
That run compiles the whole module, main and test, which is also what rules out a missed caller of the now-private methods.
mvn -Pqulicecaught the ordering problem above; after the move it reports no violations on the changed file.What I could not run here, and why
I am on Windows, and
mvn clean install -Pqulicedoes not complete on this machine for two reasons that predate this branch. I checked both by stashing the change and re-running on unmodifiedmaster, which fails identically:eo-parserfetchesblns.txtfromraw.githubusercontent.comthroughmaven-antrun-plugin, which times out here (github.comandapi.github.comare fine, that host is not). Worked around with-Dmaven.antrun.skip=true.eo-runtime'sproject-validatestep then fails withMissing: EOwin32$EOφ.class/Missing: EOposix$EOφ.class— "Not all .java files were compiled to .class files". Same failure with an empty working tree, so it is not from this change, but it does mean I have not run the full-Pqulicelifecycle end to end.Separately,
formatreports2 of 170 EO source(s) are not formatted canonicallyon a clean checkout. I left those alone — no.eofile is touched here — and used-Deo.autoFixlocally to get past it.