Skip to content

fix(values,GCString): values %h scalar context, split GCString shim into own file#622

Merged
fglock merged 1 commit intomasterfrom
feature/values-scalar-context-and-gcstring-shim-20260429-151629
Apr 29, 2026
Merged

fix(values,GCString): values %h scalar context, split GCString shim into own file#622
fglock merged 1 commit intomasterfrom
feature/values-scalar-context-and-gcstring-shim-20260429-151629

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 29, 2026

Summary

Two fixes uncovered while investigating jcpan -t User::Identity. The full dependency chain is User::IdentityLog::ReportLog::Report::UtilString::PrintUnicode::GCString, and it was failing at every step.

1. values %h in scalar context as a sub's last expression

my %h = (a => "X", b => "Y", c => "Z");
sub v { values %h }
my $n = v();   # was: "Z"   now: 3

RuntimeHash.keys() set scalarContextSize on the resulting RuntimeArray so getList() wrapped (rather than copied) it; values() did not, so the resulting list scalarized to its last element instead of the count. Affected both JVM and interpreter backends.

Fix: mirror keys() and set list.scalarContextSize = list.elements.size() in both the plain and TIED_HASH paths of RuntimeHash.values().

This was the root cause of t/30col.t failures in User::Identity, where User::Identity::Collection::roles is defined as sub roles() { values %{ $_[0]->{UIC_roles}} } and called via cmp_ok($col->roles, '==', 1, ...).

2. Unicode::GCString shim wasn't a discrete file

The pure-Perl shim of Unicode::GCString lived as a second package inside lib/Unicode/LineBreak.pm. Two problems followed:

  • use Unicode::GCString (without first loading LineBreak) couldn't find a .pm file, so it failed with "Can't locate Unicode/GCString.pm". String::Print does exactly this.
  • MakeMaker's "skip files already bundled in the PerlOnJava JAR" logic only saw Unicode/LineBreak.pm. Installing CPAN's Unicode-LineBreak distribution would therefore install/shadow the shim with the XS-needing Unicode/GCString.pm from blib, which then died with "Can't locate object method _new".

Fix: move the shim into its own file src/main/perl/lib/Unicode/GCString.pm and have LineBreak.pm require it. Now both files are visible under jar:PERL5LIB and the SKIP logic preserves both:

SKIP: Unicode/GCString.pm (bundled in PerlOnJava JAR)
SKIP: Unicode/LineBreak.pm (bundled in PerlOnJava JAR)

Result

  • jcpan -t User::Identity now passes all 114 subtests across 3 test files (was 4/4 subtests failing because use User::Identity blew up immediately).
  • String::Print test pass rate jumps from 1/19 test files to 15/19; remaining failures are wide-character column-width formatting in the shim, unrelated to this PR.

Test plan

  • make (full unit test suite) — passes
  • ./jperl -e '...' and ./jperl --interpreter -e '...' — both yield count 3 for values %h in sub-scalar context
  • ./jcpan -t User::IdentityResult: PASS, all 114 subtests successful

Generated with Devin

…ng shim

Two fixes uncovered by `jcpan -t User::Identity`:

1. `values %h` returned the LAST value (instead of the element count)
   when used as the final expression of a sub called in scalar context.
   `RuntimeHash.keys()` already set `scalarContextSize` on the result
   so `getList()` wrapped (rather than copied) it; `values()` did not,
   so the resulting list scalarized to its last element. Mirror keys()
   by setting `scalarContextSize` in both the plain and TIED_HASH paths
   of `RuntimeHash.values()`. Fixes both JVM and interpreter backends.

2. The pure-Perl `Unicode::GCString` shim used by Text::vCard et al was
   defined as a second package inside `lib/Unicode/LineBreak.pm`. Two
   consequences:

     * `use Unicode::GCString` (without first loading LineBreak) could
       not find a .pm file. String::Print does exactly that.
     * MakeMaker's "skip files bundled in the PerlOnJava JAR" logic
       only matched `Unicode/LineBreak.pm`, so installing CPAN's
       Unicode-LineBreak distribution would shadow the shim with the
       broken XS-needing version.

   Move the shim into its own file `src/main/perl/lib/Unicode/GCString.pm`
   and have LineBreak.pm `require` it. Now both files are visible under
   jar:PERL5LIB and the SKIP logic preserves both.

Together these unblock the full User::Identity dependency chain
(Log::Report -> Log::Report::Util -> String::Print -> Unicode::GCString)
so `jcpan -t User::Identity` now passes all 114 subtests.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock merged commit 32241a9 into master Apr 29, 2026
2 checks passed
@fglock fglock deleted the feature/values-scalar-context-and-gcstring-shim-20260429-151629 branch April 29, 2026 13:52
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