1--TEST--
2Ensure type hints are enforced for functions invoked as callbacks.
3--FILE--
4<?php
5
6  echo "---> Type hints with callback function:\n";
7  class A  {  }
8  function f1(A $a)  {
9      echo "in f1;\n";
10  }
11  function f2(A $a = null)  {
12      echo "in f2;\n";
13  }
14  try {
15    call_user_func('f1', 1);
16  } catch (Error $ex) {
17    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
18  }
19  try {
20    call_user_func('f1', new A);
21  } catch (Error $ex) {
22    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
23  }
24  try {
25    call_user_func('f2', 1);
26  } catch (Error $ex) {
27    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
28  }
29  try {
30    call_user_func('f2');
31  } catch (Error $ex) {
32    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
33  }
34  try {
35    call_user_func('f2', new A);
36  } catch (Error $ex) {
37    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
38  }
39  try {
40    call_user_func('f2', null);
41  } catch (Error $ex) {
42    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
43  }
44
45  echo "\n\n---> Type hints with callback static method:\n";
46  class C {
47      static function f1(A $a) {
48          if (isset($this)) {
49              echo "in C::f1 (instance);\n";
50          } else {
51              echo "in C::f1 (static);\n";
52          }
53      }
54      static function f2(A $a = null) {
55          if (isset($this)) {
56              echo "in C::f2 (instance);\n";
57          } else {
58              echo "in C::f2 (static);\n";
59          }
60      }
61  }
62
63  try {
64    call_user_func(array('C', 'f1'), 1);
65  } catch (Error $ex) {
66    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
67  }
68  try {
69    call_user_func(array('C', 'f1'), new A);
70  } catch (Error $ex) {
71    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
72  }
73  try {
74    call_user_func(array('C', 'f2'), 1);
75  } catch (Error $ex) {
76    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
77  }
78  try {
79    call_user_func(array('C', 'f2'));
80  } catch (Error $ex) {
81    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
82  }
83  try {
84    call_user_func(array('C', 'f2'), new A);
85  } catch (Error $ex) {
86    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
87  }
88  try {
89    call_user_func(array('C', 'f2'), null);
90  } catch (Error $ex) {
91    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
92  }
93
94  echo "\n\n---> Type hints with callback instance method:\n";
95  class D {
96      function f1(A $a) {
97          if (isset($this)) {
98              echo "in C::f1 (instance);\n";
99          } else {
100              echo "in C::f1 (static);\n";
101          }
102      }
103      function f2(A $a = null) {
104          if (isset($this)) {
105              echo "in C::f2 (instance);\n";
106          } else {
107              echo "in C::f2 (static);\n";
108          }
109      }
110  }
111  $d = new D;
112
113  try {
114    call_user_func(array($d, 'f1'), 1);
115  } catch (Error $ex) {
116    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
117  }
118  try {
119    call_user_func(array($d, 'f1'), new A);
120  } catch (Error $ex) {
121    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
122  }
123  try {
124    call_user_func(array($d, 'f2'), 1);
125  } catch (Error $ex) {
126    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
127  }
128  try {
129    call_user_func(array($d, 'f2'));
130  } catch (Error $ex) {
131    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
132  }
133  try {
134    call_user_func(array($d, 'f2'), new A);
135  } catch (Error $ex) {
136    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
137  }
138  try {
139    call_user_func(array($d, 'f2'), null);
140  } catch (Error $ex) {
141    echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
142  }
143
144?>
145--EXPECTF--
146Deprecated: f2(): Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d
147
148Deprecated: C::f2(): Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d
149
150Deprecated: D::f2(): Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d
151---> Type hints with callback function:
1520: f1(): Argument #1 ($a) must be of type A, int given%s(%d)
153
154in f1;
1550: f2(): Argument #1 ($a) must be of type ?A, int given%s(%d)
156
157in f2;
158in f2;
159in f2;
160
161
162---> Type hints with callback static method:
1630: C::f1(): Argument #1 ($a) must be of type A, int given%s(%d)
164
165in C::f1 (static);
1660: C::f2(): Argument #1 ($a) must be of type ?A, int given%s(%d)
167
168in C::f2 (static);
169in C::f2 (static);
170in C::f2 (static);
171
172
173---> Type hints with callback instance method:
1740: D::f1(): Argument #1 ($a) must be of type A, int given%s(%d)
175
176in C::f1 (instance);
1770: D::f2(): Argument #1 ($a) must be of type ?A, int given%s(%d)
178
179in C::f2 (instance);
180in C::f2 (instance);
181in C::f2 (instance);
182