Skip to content

fix: make Tie::File test suite pass#512

Merged
fglock merged 1 commit intomasterfrom
fix/tie-file-tests
Apr 20, 2026
Merged

fix: make Tie::File test suite pass#512
fglock merged 1 commit intomasterfrom
fix/tie-file-tests

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 20, 2026

Summary

./jcpan -t Tie::File goes from 336 failures across 16 test files to all 4725 tests passing, with no regressions in the existing unit tests.

Six related bugs in tied-array dispatch and $. handling, all fixed in the Java runtime:

  1. $. numeric reads stale zero after local $. + reads.
    ScalarSpecialVariable.set() was caching this.type=INTEGER, this.value=0 on the proxy. Readline mutates currentLineNumber directly, so the cache goes stale. Numeric comparison fast paths (arg.type==INTEGER(int)arg.value) then read 0. Removed the sync so $. always delegates through getValueAsScalar(). This is why Tie::File's _check_integrity reported "spurious caching of record N" everywhere.

  2. $. not incremented for multi-char $/.
    readUntilString only bumped currentLineNumber on \n in the line. With a custom separator containing no newline, $. stayed 0. Now increments once per record read, matching Perl.

  3. Tied push / unshift returned the tie method's raw return value.
    Perl's av.c ignores the PUSH/UNSHIFT return and reports FETCHSIZE. Tie::File's PUSH returns nothing on purpose. tiedPush / tiedUnshift now call the handler and then return FETCHSIZE.

  4. Tied SPLICE always called in scalar context.
    tieCall hardcoded SCALAR, so @r = splice(@tied, ...) got back the scalar count. Context now flows through Operator.splice and TieArray.tiedSplice to the user's SPLICE; the bytecode handler unwraps a tied scalar return directly.

  5. Negative subscripts on tied arrays passed raw to FETCH / STORE.
    Perl normalizes negative indices (FETCHSIZE + idx) before dispatch. If the result is still negative (e.g. $tied[-100] on a size-3 array), Perl does NOT call FETCH / STORE: reads yield undef, writes throw Modification of non-creatable array value attempted, subscript -N. Implemented via an outOfRangeOriginalIndex flag on RuntimeTiedArrayProxyEntry, with matching normalization in exists / delete.

  6. @tied = (...) didn't call EXTEND.
    Perl calls EXTEND on tied arrays before the STORE loop. Tie::File relies on this to extend the backing file in autodefer mode.

Test plan

  • ./jcpan -t Tie::File — 4725/4725 pass (was 4389/4725)
  • make — full unit test suite passes (no regressions)

Generated with Devin

Takes ./jcpan -t Tie::File from 336 failures / 16 failing test files
to all 4725 tests passing.

Six related bugs in tied-array and $. handling:

1. $. numeric reads stale zero after local $. + reads.
   ScalarSpecialVariable.set() cached this.type=INTEGER, this.value=0
   on the proxy. Readline mutates currentLineNumber directly, so the
   cache goes stale. Numeric comparison fast paths
   (arg.type==INTEGER -> (int)arg.value) then read 0. Removed the
   sync; $. always delegates through getValueAsScalar().

2. $. not incremented for multi-char $/.
   readUntilString only bumped currentLineNumber on '\n' in the line.
   Custom separators with no newline left $. at 0. Now increments once
   per record read, regardless of separator content.

3. Tied push/unshift returned the tie method's raw return value.
   Perl's av.c ignores the PUSH/UNSHIFT return and reports FETCHSIZE.
   Tie::File's PUSH returns nothing on purpose. tiedPush/tiedUnshift
   now call the handler and then return FETCHSIZE.

4. Tied SPLICE always called in scalar context.
   tieCall hardcoded SCALAR, so @r = splice(@tied, ...) got back the
   scalar count. Context now flows through Operator.splice and
   TieArray.tiedSplice to the user's SPLICE; the bytecode handler
   unwraps a tied scalar return directly.

5. Negative subscripts on tied arrays passed raw to FETCH/STORE.
   Perl normalizes negative indices to FETCHSIZE+idx before dispatch.
   If the result is still negative (e.g. $tied[-100] on a size-3
   array), Perl does NOT call FETCH/STORE: reads yield undef, writes
   throw "Modification of non-creatable array value attempted,
   subscript -N". Implemented via an outOfRangeOriginalIndex flag on
   RuntimeTiedArrayProxyEntry, with matching normalization in
   exists/delete.

6. @tied = (...) didn't call EXTEND.
   Perl calls EXTEND on tied arrays before the STORE loop. Tie::File
   relies on this to extend the backing file in autodefer mode.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the fix/tie-file-tests branch from 077ce69 to df54e69 Compare April 20, 2026 13:32
@fglock fglock merged commit 15d56dd into master Apr 20, 2026
2 checks passed
@fglock fglock deleted the fix/tie-file-tests branch April 20, 2026 13:58
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