1--TEST--
2call_user_func() and friends with named parameters
3--FILE--
4<?php
5
6$test = function($a = 'a', $b = 'b', $c = 'c') {
7    echo "a = $a, b = $b, c = $c\n";
8};
9$test_variadic = function(...$args) {
10    var_dump($args);
11};
12$test_ref = function(&$ref) {
13    $ref++;
14};
15$test_required = function($a, $b) {
16    echo "a = $a, b = $b\n";
17};
18
19class Test {
20    public function __construct($a = 'a', $b = 'b', $c = 'c') {
21        if (func_num_args() != 0) {
22            echo "a = $a, b = $b, c = $c\n";
23        }
24    }
25
26    public function method($a = 'a', $b = 'b', $c = 'c') {
27        echo "a = $a, b = $b, c = $c\n";
28    }
29}
30
31call_user_func($test, 'A', c: 'C');
32call_user_func($test, c: 'C', a: 'A');
33call_user_func($test, c: 'C');
34call_user_func($test_variadic, 'A', c: 'C');
35call_user_func($test_ref, ref: null);
36var_dump(call_user_func('call_user_func', $test, c: 'D'));
37try {
38    call_user_func($test_required, b: 'B');
39} catch (ArgumentCountError $e) {
40    echo $e->getMessage(), "\n";
41}
42try {
43    var_dump(call_user_func('array_slice', [1, 2, 3, 4, 5], length: 2));
44} catch (ArgumentCountError $e) {
45    echo $e->getMessage(), "\n";
46}
47try {
48    var_dump(call_user_func('array_slice', [1, 2, 3, 4, 'x' => 5], 3, preserve_keys: true));
49} catch (ArgumentCountError $e) {
50    echo $e->getMessage(), "\n";
51}
52echo "\n";
53
54$test->__invoke('A', c: 'C');
55$test_variadic->__invoke('A', c: 'C');
56$test->call(new class {}, 'A', c: 'C');
57$test_variadic->call(new class {}, 'A', c: 'C');
58echo "\n";
59
60$rf = new ReflectionFunction($test);
61$rf->invoke('A', c: 'C');
62$rf->invokeArgs(['A', 'c' => 'C']);
63$rm = new ReflectionMethod(Test::class, 'method');
64$rm->invoke(new Test, 'A', c: 'C');
65$rm->invokeArgs(new Test, ['A', 'c' => 'C']);
66$rc = new ReflectionClass(Test::class);
67$rc->newInstance('A', c: 'C');
68$rc->newInstanceArgs(['A', 'c' => 'C']);
69
70?>
71--EXPECTF--
72a = A, b = b, c = C
73a = A, b = b, c = C
74a = a, b = b, c = C
75array(2) {
76  [0]=>
77  string(1) "A"
78  ["c"]=>
79  string(1) "C"
80}
81
82Warning: {closure:%s:%d}(): Argument #1 ($ref) must be passed by reference, value given in %s on line %d
83a = a, b = b, c = D
84NULL
85{closure:%s:%d}(): Argument #1 ($a) not passed
86array_slice(): Argument #2 ($offset) not passed
87array(2) {
88  [3]=>
89  int(4)
90  ["x"]=>
91  int(5)
92}
93
94a = A, b = b, c = C
95array(2) {
96  [0]=>
97  string(1) "A"
98  ["c"]=>
99  string(1) "C"
100}
101a = A, b = b, c = C
102array(2) {
103  [0]=>
104  string(1) "A"
105  ["c"]=>
106  string(1) "C"
107}
108
109a = A, b = b, c = C
110a = A, b = b, c = C
111a = A, b = b, c = C
112a = A, b = b, c = C
113a = A, b = b, c = C
114a = A, b = b, c = C
115