Conversation
…Ix::Class fixes
The bytecode interpreter (used by eval STRING) was eagerly evaluating
the RHS of //=, ||=, &&= before checking the short-circuit condition.
This caused side effects like $counter++ to always execute, breaking
DBIx::Class eval-generated row collapser code where //= is used to
deduplicate joined rows (prefetch result collapsing).
The fix adds handleShortCircuitAssignment() which:
1. Compiles the LHS first
2. Emits a conditional jump (GOTO_IF_TRUE/FALSE) to skip RHS
3. Only compiles and evaluates the RHS if the condition is not met
4. Assigns via SET_SCALAR only when needed
Also includes:
- Parser {} disambiguation: added insideDereference flag so
%{{ map {...} @list }} is correctly parsed as hash (not block)
inside dereference context
- DBI last_insert_id(): use connection-level SQL queries instead of
statement-level getGeneratedKeys() which broke when prepare() was
called between INSERT and last_insert_id()
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Added documentation for:
- 5.35: last_insert_id() connection-level SQL fix
- 5.36: %{{ expr }} parser disambiguation fix
- 5.37: //=, ||=, &&= short-circuit fix in bytecode interpreter
- Updated t/83cache.t and t/90join_torture.t as FIXED
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…st results Updated with full test suite scan (314 files, 96.7% pass rate): - Rewrote Remaining Real Failures with 6 root cause clusters - Added dependency module test results (97.6% aggregate) - Added tiered implementation plan (steps 5.38-5.46) - Marked t/101populate_rs.t and t/90ensure_class_loaded.t as FIXED - Updated blocking issues to mark resolved items - Updated t/60core.t results (170 tests breakdown) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…::Class
Three fixes to improve DBIx::Class compatibility:
1. Fix *{stash_entry} = \ creating spurious constant subs
- In Perl 5, *glob = \ only sets the SCALAR slot
- PerlOnJava was incorrectly creating a CODE slot (constant sub) when
the glob was obtained via stash hash lookup
- This corrupted constants after namespace::clean removed and restored
glob slots, causing UNRESOLVABLE_CONDITION in DBIx::Class to return
dereferenced string instead of scalar ref
- Fix: globDeref() now returns a plain RuntimeGlob when unwrapping a
RuntimeStashEntry, so assignment dispatches to RuntimeGlob.set()
- Fixes t/60core.t test 38 (-and array condition in find())
2. Add VIVIFY_LVALUE opcode for hash element lvalue vivification
- ||=, &&=, //= on hash elements now vivify the entry before
evaluating the RHS, matching Perl 5 behavior
- Fixes 16 ORDER_BY tests in DBIx::Class SQLMaker limit dialects
3. Fix DBI prepare_cached error message rewriting
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Replace YAML+GZIP Storable freeze/nfreeze with a binary serializer matching Perl 5 Storable type byte ordering and value-before-key hash entry format. This fixes DBIC _collapse_cond which uses nfreeze output as hash keys for condition deduplication/sorting. Key changes: - Storable: Binary format with Storable-compatible type bytes - Storable: Hash entries written VALUE-first then KEY - Storable: thaw handles both new binary and legacy YAML formats - DBI: Add HandleError callback support for error wrapping - DBI: Fix prepare_cached error message format Generated with Devin (https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
When an undef scalar was hashDeref multiple times before any write each call created a separate autovivification hash. The second vivification would overwrite the first, orphaning its data. Fix: cache the autovivification hash/array in the scalar value field (type remains UNDEF) so subsequent deref calls reuse the same container. Read-only access is unaffected. Also fixes the same bug for arrays. Resolves DBIx::Class t/relationship/custom_opaque.t (2 tests). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ref(\\$x) returned "SCALAR" instead of "REF" because REFERENCE type was missing from the inner switch in ReferenceOperators.ref(). When a REFERENCE pointed to another REFERENCE, it fell through to the default case. Also fixed the parallel bug in builtin::reftype (Builtin.java). Fixes SQL-Abstract-Classic t/09refkind.t (13/13, was 9/13). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… 10) Implements per-call-site tracking of compile-time hints for caller(): - caller()[8] now returns accurate $^H value (was hardcoded to 0) - caller()[10] now returns %^H hash reference (was hardcoded to undef) Architecture follows the same pattern as caller()[9] warning bits: - WarningBitsRegistry tracks callSiteHints/callSiteHintHash ThreadLocals - EmitCompilerFlag emits setCallSiteHints/snapshotCurrentHintHash bytecode - RuntimeCode.apply() pushes/pops hints across subroutine calls - BEGIN block $^H propagation now updates all scope levels This enables Sub::Quote's _context() mechanism which captures caller hints to restore strict/warnings state in eval'd code (needed for DBIx::Class). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- get_isarev: replaced hardcoded class list with dynamic scan of all @isa arrays via GlobalVariable.getAllIsaArrays() - get_pkg_gen: added lazy @isa change detection — compares current @isa to cached state and auto-increments on change - get_pkg_gen: incremented on CODE assignment to globs (RuntimeGlob.set) - Made Mro.incrementPackageGeneration() public for cross-package use MRO-Compat now passes 26/26 tests (was 22/26). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ings)
When the bytecode interpreter creates sub-compilers for anonymous/named
subroutines, they now inherit strict, warning, and feature flags from the
parent compiler. Previously, sub-compilers started with default (0) flags,
so BEGIN { $^H = ... } changes did not propagate into sub bodies.
Also added getEffectiveSymbolTable() that falls back to this.symbolTable
when emitterContext is null (the case for sub-compilers), so
isStrictRefsEnabled() and similar methods work correctly in sub bodies.
Sub::Quote hints.t: tests 1-2 now pass (strict refs preserved in quoted subs).
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- warn() now always returns 1 (was returning undef), matching Perl 5.
This also applies when $SIG{__WARN__} is set.
Fixes SQL-Abstract-Classic t/02where.t IS NULL generation.
- Overload fallback now reads SCALAR slot of () glob instead of
calling the CODE slot which always returns undef.
- When no fallback is specified, autogeneration is now allowed.
- Binary operators die with no method found when overloading is
active but fallback does not allow native operations.
- Compound assignment operators try autogeneration from base
operators before dying.
SQL-Abstract-Classic: 1228/1228 -> 1311/1311 (100%)
Generated with Devin (https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Rewrite B.pm SV flag constants to standard Perl 5 values (SVf_IOK=0x100, SVf_NOK=0x200, SVf_POK=0x400, SVp_IOK=0x1000, SVp_NOK=0x2000, SVp_POK=0x4000) - Rewrite FLAGS() to use builtin::created_as_number() for proper integer/float/string type distinction - Fix large integer literals (>= 2^31) stored as DOUBLE instead of STRING in both JVM emitter and bytecode interpreter, matching Perl 5 IV-to-NV promotion behavior - SQL-Abstract-Classic: 100% (1311/1311), was 98.5% - Sub-Quote quotify.t: 2592/2592, was 2586/2592 Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Three fixes for Sub::Quote test improvements: 1. caller() frame skip for interpreter code: ExceptionFormatter now returns metadata indicating whether the first frame was from the interpreter (CallerStack, already the call site) vs JVM (sub own location, needs skip). callerWithSub() uses this to conditionally skip the first frame. Fixes caller(0) returning wrong file/line when called from anonymous subs inside eval STRING with #line. 2. List slice in interpreter: (list)[indices] was incorrectly compiled as [list]->[indices] (array ref dereference returning one scalar). Added LIST_SLICE opcode that calls RuntimeList.getSlice() for proper multi-element list slice semantics. 3. Sub naming in eval: SubroutineParser now uses fully qualified names via NameNormalizer so ByteCodeSourceMapper records the correct declaration-time package. Also fixed eval STRING ErrorMessageUtil to use evalCtx.compilerOptions.fileName instead of the outer file. Sub::Quote: 54/56 (was 52/56). Tests 48,50,55,56 now pass. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The LIST_SLICE opcode returns a RuntimeList, but when used in scalar context (e.g., from a $$ prototype like is()), the list was not being converted to a scalar value. This caused (unpack(...))[0] to return the list count (1) instead of the actual element value (e.g., 300). Added LIST_TO_SCALAR opcode emission after LIST_SLICE when the compilation context is SCALAR, matching how the JVM backend handles this case in Dereference.java. Fixes op/pack.t regression (-2 tests) that only manifested when the main program was large enough to trigger interpreter fallback. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… objects Previously, only dclone() (via deepClone()) called STORABLE_freeze/thaw hooks on blessed objects. The binary serialization path used by freeze()/nfreeze()/thaw() raw-serialized blessed objects without hooks, causing objects with non-serializable internals (e.g., DBI handles with JDBC connections) to produce corrupt frozen data. Added SX_HOOK (type 19) to binary format for hook-serialized objects. serializeBinary() now checks for STORABLE_freeze before SX_BLESS, and deserializeBinary() handles SX_HOOK by calling STORABLE_thaw. Impact: t/84serialize.t goes from 1 real failure to 0 (115/115 pass). Also updated design doc with corrected DBIx::Class failure analysis — 59 of 63 active test programs now pass all real tests (94%). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- prepare() sets sth Active=false (was inheriting dbh Active=true) - execute() sets Active=true only for SELECTs with result sets - fetchrow_arrayref/hashref set Active=false when rows exhausted - execute() closes previous JDBC ResultSet before re-executing - Use mutable RuntimeScalar (not read-only scalarFalse) for Active Results: t/60core.t goes from 50 failures (45 cached stmt + 5 GC) to 17 failures (12 cached stmt + 5 GC). Remaining 12 need DESTROY. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
213ed5e to
003b368
Compare
- op/assignwarn.t: Add integerDivideWarn/integerDivideAssignWarn for
uninitialized value warnings with /= under "use integer" in bytecode
interpreter and JVM backend
- op/while.t: Add constant condition optimization to do{}while/until
loops, fold reference constants to true without triggering overloads
- op/vec.t: Fix unsigned 32-bit vec values using getLong() for 32/64-bit
- op/assignwarn.t: Fixes tests 24, 82 (116/116 pass)
- op/while.t: Fixes test 26 (23/26 pass, 12-14 pre-existing)
- Includes prior fixes: strict options propagation, caller()[10] hints,
%- CAPTURE_ALL array refs, large integer literal handling
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…fixes) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- j/J format now packs/unpacks as 4-byte int (matching ivsize=4) instead of hardcoded 8-byte long - q/Q format now throws "Invalid type" matching 32-bit Perl without use64bitint — tests that use q/Q are gracefully skipped - op/pack.t: +5 passes (14665 ok); op/64bitint.t: fully skipped Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Since pack "q" is no longer supported (ivsize=4), sprintf %lld/%lli/ %llu/%Ld/%Li/%Lu must also be rejected as invalid conversions, matching 32-bit Perl behavior. Fixes op/sprintf2.t regression (-24). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
In Perl, Inf/NaN handling takes priority over format validation.
sprintf("%lld", Inf) returns "Inf" with no warning, even though
%lld is an invalid format on 32-bit Perl. Previously, our quad
format rejection would return the raw format string "%lld" and
emit an "Invalid conversion" warning even for Inf/NaN values.
Now, when a format specifier is marked invalid but the argument
is Inf/NaN, we bypass the invalid handling and format the special
value directly. This fixes 33 test failures in op/infnan.t while
maintaining the correct behavior for non-Inf/NaN values in
op/sprintf2.t.
Test results:
- op/infnan.t: 1086/1088 (was 1053/1088, +33)
- op/sprintf2.t: 1652/1655 (unchanged)
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.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.
Summary
Three fixes for DBIx::Class test failures:
//=,||=,&&=short-circuit in bytecode interpreter: The bytecode compiler (used byeval STRING) was eagerly evaluating the RHS before checking the short-circuit condition. Side effects like$result_pos++always executed, breaking DBIx::Class's eval-generated row collapser code where//=deduplicates joined rows during prefetch result collapsing. AddedhandleShortCircuitAssignment()that compiles LHS first, emits conditional jump (GOTO_IF_TRUE/GOTO_IF_FALSE) to skip RHS, and only evaluates and assigns viaSET_SCALARwhen needed.Parser
{}disambiguation inside%{...}dereference context:%{{ map { ... } @list }}was parsed as a block instead of a hash reference when inside a dereference context. AddedinsideDereferenceflag to Parser soisHashLiteral()defaults to hash when there are no block indicators. Fixes RowParser.pm__unique_numlistand Ordered.pmvalues %{{ ... }}patterns.DBI
last_insert_id()connection-level queries: Replaced statement-levelgetGeneratedKeys()with connection-level SQL (SELECT last_insert_rowid()for SQLite, etc.). The old approach broke when anyprepare()call between INSERT andlast_insert_id()overwrote the stored statement handle.DBIx::Class tests fixed
%{{ map {...} @list }}parsingvalues %{{ ... }}parsingFiles changed
BytecodeCompiler.javahandleCompoundAssignment()to defer RHS evaluation for//=, `Parser.javainsideDereferenceflagStatementResolver.javaisHashLiteral()checksinsideDereferenceflagVariable.javaparseBracedVariable()setsinsideDereferencebefore parsingDBI.javalast_insert_id()uses connection-level SQL queriesdev/modules/dbix_class.mdTest plan
makepasses (all unit tests)//=short-circuits correctly in eval (isolated test)||=and&&=short-circuit correctly in eval//=/||=/&&=still works (JVM backend unaffected)Generated with Devin