From 8344ae114443e495bd19fee630faff286cc15c8e Mon Sep 17 00:00:00 2001 From: "Flavio S. Glock" Date: Wed, 28 Oct 2026 16:15:12 +0100 Subject: [PATCH 1/2] fix: preserve lvalue returns through goto markers Defer lvalue-return validation while a goto &sub control-flow marker is being forwarded, so the replacement subroutine can return its writable undef-valued scalar cell. Keep validation for actual empty lvalue returns. Fixes #1915 Generated with [Codex](https://openai.com/codex/) Co-Authored-By: Codex --- dev/design/issue-queue.md | 3 +- docs/about/changelog.md | 1 + .../runtime/runtimetypes/RuntimeCode.java | 6 ++++ .../unit/lvalue_sub_goto_undef_alias.t | 28 +++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/unit/lvalue_sub_goto_undef_alias.t diff --git a/dev/design/issue-queue.md b/dev/design/issue-queue.md index eceb2d1fd2..a0d9e8eb57 100644 --- a/dev/design/issue-queue.md +++ b/dev/design/issue-queue.md @@ -1,6 +1,6 @@ # Reviewed issue queues -Snapshot: 2026-10-27, from live open issues, PRs and the #1649 phase contract. +Snapshot: 2026-10-28, from live open issues, PRs and the #1649 phase contract. This is a bounded selection aid, not the complete backlog or fresh runtime validation. Follow the [triage and claim protocol](../../docs/guides/issue-triage.md) and recheck live issue comments/PRs before starting. Unlisted work is unreviewed @@ -33,6 +33,7 @@ resolved before implementation. No new pass or failure is asserted here. | Frontend constants/quoting | [#1376](https://github.com/fglock/PerlOnJava/issues/1376) Constant hash-reference dereference | High / Investigate | Both-backend suite failures are reported. Minimize constant folding/dereference behavior and establish a failing current parent before selecting the fix. | | Parser syntax | [#1427](https://github.com/fglock/PerlOnJava/issues/1427) Test::Unit / Error.pm | Normal / Investigate | Separate catch-syntax behavior from example-path normalization; retain the full passing Perl comparison and identify independently fixable causes. | | Calls and value operations | [#1448](https://github.com/fglock/PerlOnJava/issues/1448) Audit-wrapper recursion | High / Investigate | Runaway recursion on both backends with a passing Perl suite. Trace captured original coderef identity and wrapper replacement under a timeout; no proven #1649 dependency. | +| Lvalue return flow | [#1915](https://github.com/fglock/PerlOnJava/issues/1915) Undef aliases through `goto` | Normal / Active | [Current claim](https://github.com/fglock/PerlOnJava/issues/1915#issuecomment-6472368217); parent reproducer passes system Perl and fails both backends. Preserve the invalid empty scalar-return diagnostic; PR pending. | | Calls and value operations | [#1342](https://github.com/fglock/PerlOnJava/issues/1342) Relational overload dispatch | Normal / Ready | Report identifies an unwanted `cmp` dispatch. Add direct relational-overload coverage and require Morpheus acceptance on both backends. | | Calls and value operations | [#1428](https://github.com/fglock/PerlOnJava/issues/1428) Decimal stringification | Normal / Ready | One DateTime::Format::Epoch mismatch with passing Perl suite. Reduce the numeric conversion and cover large integral results without scientific notation. | | Warnings category tables | [#1208](https://github.com/fglock/PerlOnJava/issues/1208), [#1219](https://github.com/fglock/PerlOnJava/issues/1219) Experimental categories | Normal / Ready | Unknown valid categories prevent module load. Check shared registration code, add category-specific focused tests and upstream load acceptance; batch only if one registration mechanism owns both. | diff --git a/docs/about/changelog.md b/docs/about/changelog.md index a5ebb30201..a1f591b52a 100644 --- a/docs/about/changelog.md +++ b/docs/about/changelog.md @@ -11,6 +11,7 @@ priorities and future plans. - Export `fieldhash` from `Hash::Util` for compatibility with core Perl. - Normalize tied-hash `exists` results to Perl's boolean values. +- Preserve lvalue returns through `goto &sub` without validating the empty control-flow marker (#1915). - Preserve reference lifetime when overloaded `++` and `--` fall back to arithmetic (#1901). - Parse forward-declared qualified classes as indirect constructors inside `new` methods (#1899). diff --git a/src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeCode.java b/src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeCode.java index a068fbd521..2033a30b8e 100644 --- a/src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeCode.java +++ b/src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeCode.java @@ -2171,6 +2171,12 @@ public static RuntimeScalar keysLvalue(RuntimeBase container) { } public static RuntimeList returnList(RuntimeBase retVal, int callContext, boolean copyReferenceScalars) { + // A control-flow marker has not produced a Perl return value yet. In + // particular, goto &sub must reach its replacement subroutine before + // lvalue-return validation; the marker itself is intentionally empty. + if (retVal instanceof RuntimeControlFlowList) { + return (RuntimeList) retVal; + } requireWritableLvalueReturn(callContext, retVal); if (retVal == null) { requireNonemptyLvalueReturn(callContext, null); diff --git a/src/test/resources/unit/lvalue_sub_goto_undef_alias.t b/src/test/resources/unit/lvalue_sub_goto_undef_alias.t new file mode 100644 index 0000000000..e287ab7776 --- /dev/null +++ b/src/test/resources/unit/lvalue_sub_goto_undef_alias.t @@ -0,0 +1,28 @@ +use strict; +use warnings; +use Test::More; + +my $slot; + +sub lvalue_target :lvalue { + $slot; +} + +lvalue_target() = 'direct'; +is($slot, 'direct', 'lvalue sub returns a writable undef slot'); + +undef $slot; +sub lvalue_goto_wrapper :lvalue { + goto &lvalue_target; +} + +lvalue_goto_wrapper() = 'assigned'; +is($slot, 'assigned', 'goto lvalue wrapper forwards a writable undef slot'); + +sub empty_lvalue_return :lvalue {} +my $error; +eval { empty_lvalue_return() = 'replacement'; 1 } or $error = $@; +like($error, qr/^Can't return undef from lvalue subroutine/, + 'empty lvalue return remains invalid'); + +done_testing; From 6ccddec300692a0e4bcb0ecd2cfbc6740bde4618 Mon Sep 17 00:00:00 2001 From: "Flavio S. Glock" Date: Wed, 28 Oct 2026 16:42:35 +0100 Subject: [PATCH 2/2] docs: link issue queue to lvalue fix PR Record draft PR #1917 and its current validation state in the project issue queue. Generated with [Codex](https://openai.com/codex/) Co-Authored-By: Codex --- dev/design/issue-queue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/design/issue-queue.md b/dev/design/issue-queue.md index a0d9e8eb57..40dc0bafd4 100644 --- a/dev/design/issue-queue.md +++ b/dev/design/issue-queue.md @@ -33,7 +33,7 @@ resolved before implementation. No new pass or failure is asserted here. | Frontend constants/quoting | [#1376](https://github.com/fglock/PerlOnJava/issues/1376) Constant hash-reference dereference | High / Investigate | Both-backend suite failures are reported. Minimize constant folding/dereference behavior and establish a failing current parent before selecting the fix. | | Parser syntax | [#1427](https://github.com/fglock/PerlOnJava/issues/1427) Test::Unit / Error.pm | Normal / Investigate | Separate catch-syntax behavior from example-path normalization; retain the full passing Perl comparison and identify independently fixable causes. | | Calls and value operations | [#1448](https://github.com/fglock/PerlOnJava/issues/1448) Audit-wrapper recursion | High / Investigate | Runaway recursion on both backends with a passing Perl suite. Trace captured original coderef identity and wrapper replacement under a timeout; no proven #1649 dependency. | -| Lvalue return flow | [#1915](https://github.com/fglock/PerlOnJava/issues/1915) Undef aliases through `goto` | Normal / Active | [Current claim](https://github.com/fglock/PerlOnJava/issues/1915#issuecomment-6472368217); parent reproducer passes system Perl and fails both backends. Preserve the invalid empty scalar-return diagnostic; PR pending. | +| Lvalue return flow | [#1915](https://github.com/fglock/PerlOnJava/issues/1915) Undef aliases through `goto` | Normal / Active | [Draft PR #1917](https://github.com/fglock/PerlOnJava/pull/1917) is open; [current claim](https://github.com/fglock/PerlOnJava/issues/1915#issuecomment-6472368217) records the passing local gates and current CI run. | | Calls and value operations | [#1342](https://github.com/fglock/PerlOnJava/issues/1342) Relational overload dispatch | Normal / Ready | Report identifies an unwanted `cmp` dispatch. Add direct relational-overload coverage and require Morpheus acceptance on both backends. | | Calls and value operations | [#1428](https://github.com/fglock/PerlOnJava/issues/1428) Decimal stringification | Normal / Ready | One DateTime::Format::Epoch mismatch with passing Perl suite. Reduce the numeric conversion and cover large integral results without scientific notation. | | Warnings category tables | [#1208](https://github.com/fglock/PerlOnJava/issues/1208), [#1219](https://github.com/fglock/PerlOnJava/issues/1219) Experimental categories | Normal / Ready | Unknown valid categories prevent module load. Check shared registration code, add category-specific focused tests and upstream load acceptance; batch only if one registration mechanism owns both. |