diff --git a/Zend/tests/trampoline_closure_named_arguments.phpt b/Zend/tests/trampoline_closure_named_arguments.phpt index e209853e509cb..e4ccaf16e63a6 100644 --- a/Zend/tests/trampoline_closure_named_arguments.phpt +++ b/Zend/tests/trampoline_closure_named_arguments.phpt @@ -14,12 +14,15 @@ class Test { $test = new Test; +$array = ["unpacked"]; + echo "-- Non-static cases --\n"; $test->test(1, 2, a: 123); $test->test(...)(1, 2); $test->test(...)(1, 2, a: 123, b: $test); $test->test(...)(a: 123, b: $test); $test->test(...)(); +$test->test(...)(...$array); echo "-- Static cases --\n"; Test::testStatic(1, 2, a: 123); @@ -27,6 +30,16 @@ Test::testStatic(...)(1, 2); Test::testStatic(...)(1, 2, a: 123, b: $test); Test::testStatic(...)(a: 123, b: $test); Test::testStatic(...)(); +Test::testStatic(...)(...$array); + +echo "-- Reflection tests --\n"; +$reflectionFunction = new ReflectionFunction(Test::fail(...)); +var_dump($reflectionFunction->getParameters()); +$argument = $reflectionFunction->getParameters()[0]; +var_dump($argument->isVariadic()); +$type = $argument->getType(); +var_dump($type); +var_dump($type->getName()); ?> --EXPECT-- @@ -70,6 +83,11 @@ array(2) { string(4) "test" array(0) { } +string(4) "test" +array(1) { + [0]=> + string(8) "unpacked" +} -- Static cases -- string(10) "testStatic" array(3) { @@ -110,3 +128,20 @@ array(2) { string(10) "testStatic" array(0) { } +string(10) "testStatic" +array(1) { + [0]=> + string(8) "unpacked" +} +-- Reflection tests -- +array(1) { + [0]=> + object(ReflectionParameter)#4 (1) { + ["name"]=> + string(9) "arguments" + } +} +bool(true) +object(ReflectionNamedType)#5 (0) { +} +string(5) "mixed" diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 69eeb3cf1ceef..2072eac72d712 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -833,6 +833,9 @@ ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_clas } /* }}} */ +/* __call and __callStatic name the arguments "$arguments" in the docs. */ +static zend_internal_arg_info trampoline_arg_info[] = {ZEND_ARG_VARIADIC_TYPE_INFO(false, arguments, IS_MIXED, false)}; + void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {{{ */ zval instance; zend_internal_function trampoline; @@ -856,6 +859,9 @@ void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* { trampoline.handler = zend_closure_call_magic; trampoline.function_name = mptr->common.function_name; trampoline.scope = mptr->common.scope; + if (trampoline.fn_flags & ZEND_ACC_VARIADIC) { + trampoline.arg_info = trampoline_arg_info; + } zend_free_trampoline(mptr); mptr = (zend_function *) &trampoline;