From 8be62dafb3d5c63709731ea45e6098528e7621f7 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 14 Jul 2026 14:27:08 +0800 Subject: [PATCH] Optimize discarded trailing return values --- phpunit/code/multi-return-tuple.php | 8 ++++++++ phpunit/src/MultiReturnTest.php | 8 ++++++++ src/Parser/AssignOpTrait.php | 8 ++++++-- .../array/multi-return-discard-tail.phpt | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/compiler/array/multi-return-discard-tail.phpt diff --git a/phpunit/code/multi-return-tuple.php b/phpunit/code/multi-return-tuple.php index e2eb4c87..e38ba6f9 100644 --- a/phpunit/code/multi-return-tuple.php +++ b/phpunit/code/multi-return-tuple.php @@ -10,6 +10,14 @@ function phpunit_multi_consumer(): void { [$first, $second] = phpunit_multi_values(); $array = phpunit_multi_values(); + + [$partialFirst, $partialSecond] = phpunit_multi_three_values(); + [$overflowFirst, $overflowSecond, $overflowThird] = phpunit_multi_values(); +} + +function phpunit_multi_three_values(): array +{ + return [1, 2, 3]; } function phpunit_multi_side_effect(): array diff --git a/phpunit/src/MultiReturnTest.php b/phpunit/src/MultiReturnTest.php index 0a4bd13d..27a0a09c 100644 --- a/phpunit/src/MultiReturnTest.php +++ b/phpunit/src/MultiReturnTest.php @@ -32,6 +32,14 @@ final class MultiReturnTest extends TestCase 'array = php_phpunit_multi_values()', $code, ); + $this->assertStringContainsString( + 'std::tie(partialFirst, partialSecond, std::ignore) = typephp::detail::php_phpunit_multi_three_values()', + $code, + ); + $this->assertStringNotContainsString( + 'std::tie(overflowFirst, overflowSecond, overflowThird)', + $code, + ); $this->assertStringNotContainsString( 'typephp::detail::php_phpunit_multi_side_effect', $code, diff --git a/src/Parser/AssignOpTrait.php b/src/Parser/AssignOpTrait.php index c8885a17..cf826761 100644 --- a/src/Parser/AssignOpTrait.php +++ b/src/Parser/AssignOpTrait.php @@ -123,7 +123,7 @@ trait AssignOpTrait } $functionDef = $this->getFunction($nativeFunc); if (!$functionDef->hasMultiReturn() - || $functionDef->multiReturnCount !== count($left->items) + || $functionDef->multiReturnCount < count($left->items) || $this->shouldUseDynamicCallForNativeArgs($nativeFunc, $right->args)) { return null; } @@ -146,8 +146,12 @@ trait AssignOpTrait $this->addLocalVar($name, Type::VAR); } } + $tieItems = array_merge( + $variables, + array_fill(0, $functionDef->multiReturnCount - count($variables), 'std::ignore'), + ); $right->setAttribute(self::ATTR_MULTI_RETURN_IMPL, true); - return 'std::tie(' . implode(', ', $variables) . ') = ' . $this->parseFuncCall($right); + return 'std::tie(' . implode(', ', $tieItems) . ') = ' . $this->parseFuncCall($right); } protected function parseAssignToList(Expr $left, Expr $right): string diff --git a/tests/compiler/array/multi-return-discard-tail.phpt b/tests/compiler/array/multi-return-discard-tail.phpt new file mode 100644 index 00000000..7927de5b --- /dev/null +++ b/tests/compiler/array/multi-return-discard-tail.phpt @@ -0,0 +1,18 @@ +--TEST-- +Tuple multi-return fast path can discard trailing values +--FILE-- + +--EXPECT-- +int(1) +int(2)