diff --git a/dev/design/issue-queue.md b/dev/design/issue-queue.md index eceb2d1fd2..40dc0bafd4 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 | [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. | 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;