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