Summary
PerlOnJava does not emit Perl's Deep recursion warning for sufficiently deep recursive calls. The behavior is missing on both the JVM and interpreter backends.
Evidence
The Tree 1.16 CPAN test suite exposed this in t/Tree/018_no_fatal_warnings.t during CPAN run 20260902-105744-25704.
- Native system Perl: all applicable tests pass. The optional
Test::Memory::Cycle test is skipped because that optional dependency is not installed.
- PerlOnJava JVM backend:
t/Tree/018_no_fatal_warnings.t fails 1 of 2 assertions.
- PerlOnJava interpreter backend: the same focused test fails 1 of 2 assertions.
- The first assertion passes on both backends: recursion does not become fatal under
warnings FATAL => 'all'.
- The second assertion fails because the warning handler receives no warning.
Minimal reproducer
use strict;
use warnings;
use Test::More;
use Tree;
my $warning;
local $SIG{__WARN__} = sub { $warning = $_[0] };
my ($i, $node);
my $tree = Tree->new('root');
$node = $tree;
my $ok = eval {
for ($i = 0; $i < 100; $i++) {
my $child = Tree->new("child $i");
$node->add_child({}, $child);
$node = $child;
}
1;
};
ok $ok, 'deep recursion is not fatal';
like $warning, qr/Deep recursion/, 'deep recursion warning is emitted';
done_testing;
Native Perl reports a warning matching Deep recursion through the localized warning handler. PerlOnJava reports the first assertion as successful but leaves $warning undefined, causing the second assertion to fail.
Impact
Programs that rely on Perl's deep-recursion diagnostics cannot observe the warning under PerlOnJava. This can hide accidental unbounded recursion and causes compatibility failures in modules that test warning behavior. The recursion itself is not incorrectly made fatal in this case.
Suggested investigation
- Locate the recursion-depth tracking or call-dispatch path used by both execution backends.
- Compare the warning threshold and warning text with native Perl.
- Ensure the warning is delivered through Perl's normal warning machinery and reaches localized
SIG{__WARN__} handlers.
- Confirm that
warnings FATAL => 'all' still converts the warning to an exception when requested.
- Add permanent project-owned tests covering shallow recursion, threshold crossing, localized warning handlers, and fatal-warning mode on both backends.
Acceptance criteria
- The reproducer emits a
Deep recursion warning on both PerlOnJava backends.
- The warning is capturable through
SIG{__WARN__} and has Perl-compatible text/category behavior.
warnings FATAL => 'all' makes the warning fatal, while a localized warning handler can observe it when warnings are non-fatal.
- The focused regression test and the
Tree upstream test pass on JVM and interpreter backends.
Summary
PerlOnJava does not emit Perl's
Deep recursionwarning for sufficiently deep recursive calls. The behavior is missing on both the JVM and interpreter backends.Evidence
The
Tree1.16 CPAN test suite exposed this int/Tree/018_no_fatal_warnings.tduring CPAN run20260902-105744-25704.Test::Memory::Cycletest is skipped because that optional dependency is not installed.t/Tree/018_no_fatal_warnings.tfails 1 of 2 assertions.warnings FATAL => 'all'.Minimal reproducer
Native Perl reports a warning matching
Deep recursionthrough the localized warning handler. PerlOnJava reports the first assertion as successful but leaves$warningundefined, causing the second assertion to fail.Impact
Programs that rely on Perl's deep-recursion diagnostics cannot observe the warning under PerlOnJava. This can hide accidental unbounded recursion and causes compatibility failures in modules that test warning behavior. The recursion itself is not incorrectly made fatal in this case.
Suggested investigation
SIG{__WARN__}handlers.warnings FATAL => 'all'still converts the warning to an exception when requested.Acceptance criteria
Deep recursionwarning on both PerlOnJava backends.SIG{__WARN__}and has Perl-compatible text/category behavior.warnings FATAL => 'all'makes the warning fatal, while a localized warning handler can observe it when warnings are non-fatal.Treeupstream test pass on JVM and interpreter backends.