1--TEST-- 2Test "or null"/"or be null" in type-checking errors for userland functions 3--FILE-- 4<?php 5 6// This should test every branch in zend_execute.c's `zend_verify_arg_type`, `zend_verify_return_type` and `zend_verify_missing_return_type` functions which produces an "or null"/"or be null" part in its error message 7 8function unloadedClass(?I\Dont\Exist $param) {} 9 10try { 11 unloadedClass(new \StdClass); 12} catch (\TypeError $e) { 13 echo $e, PHP_EOL; 14} 15 16class RealClass {} 17interface RealInterface {} 18 19function loadedClass(?RealClass $param) {} 20function loadedInterface(?RealInterface $param) {} 21 22try { 23 loadedClass(new \StdClass); 24} catch (\TypeError $e) { 25 echo $e, PHP_EOL; 26} 27 28try { 29 loadedInterface(new \StdClass); 30} catch (\TypeError $e) { 31 echo $e, PHP_EOL; 32} 33 34try { 35 unloadedClass(1); 36} catch (\TypeError $e) { 37 echo $e, PHP_EOL; 38} 39 40try { 41 loadedClass(1); 42} catch (\TypeError $e) { 43 echo $e, PHP_EOL; 44} 45 46try { 47 loadedInterface(1); 48} catch (\TypeError $e) { 49 echo $e, PHP_EOL; 50} 51 52function callableF(?callable $param) {} 53 54try { 55 callableF(1); 56} catch (\TypeError $e) { 57 echo $e, PHP_EOL; 58} 59 60function intF(?int $param) {} 61 62try { 63 intF(new StdClass); 64} catch (\TypeError $e) { 65 echo $e, PHP_EOL; 66} 67 68function returnUnloadedClass(): ?I\Dont\Exist { 69 return new \StdClass; 70} 71 72try { 73 returnUnloadedClass(); 74} catch (\TypeError $e) { 75 echo $e, PHP_EOL; 76} 77 78function returnLoadedClass(): ?RealClass { 79 return new \StdClass; 80} 81 82try { 83 returnLoadedClass(); 84} catch (\TypeError $e) { 85 echo $e, PHP_EOL; 86} 87 88function returnLoadedInterface(): ?RealInterface { 89 return new \StdClass; 90} 91 92try { 93 returnLoadedInterface(); 94} catch (\TypeError $e) { 95 echo $e, PHP_EOL; 96} 97 98function returnUnloadedClassScalar(): ?I\Dont\Exist { 99 return 1; 100} 101 102try { 103 returnUnloadedClassScalar(); 104} catch (\TypeError $e) { 105 echo $e, PHP_EOL; 106} 107 108function returnLoadedClassScalar(): ?RealClass { 109 return 1; 110} 111 112try { 113 returnLoadedClassScalar(); 114} catch (\TypeError $e) { 115 echo $e, PHP_EOL; 116} 117 118function returnLoadedInterfaceScalar(): ?RealInterface { 119 return 1; 120} 121 122try { 123 returnLoadedInterfaceScalar(); 124} catch (\TypeError $e) { 125 echo $e, PHP_EOL; 126} 127 128function returnCallable(): ?callable { 129 return 1; 130} 131 132try { 133 returnCallable(); 134} catch (\TypeError $e) { 135 echo $e, PHP_EOL; 136} 137 138function returnInt(): ?int { 139 return new \StdClass; 140} 141 142try { 143 returnInt(); 144} catch (\TypeError $e) { 145 echo $e, PHP_EOL; 146} 147 148function returnMissingUnloadedClass(): ?I\Dont\Exist { 149} 150 151try { 152 returnMissingUnloadedClass(); 153} catch (\TypeError $e) { 154 echo $e, PHP_EOL; 155} 156 157function returnMissingLoadedClass(): ?RealClass { 158} 159 160try { 161 returnMissingLoadedClass(); 162} catch (\TypeError $e) { 163 echo $e, PHP_EOL; 164} 165 166function returnMissingLoadedInterface(): ?RealInterface { 167} 168 169try { 170 returnMissingLoadedInterface(); 171} catch (\TypeError $e) { 172 echo $e, PHP_EOL; 173} 174 175function returnMissingCallable(): ?callable { 176} 177 178try { 179 returnMissingCallable(); 180} catch (\TypeError $e) { 181 echo $e, PHP_EOL; 182} 183 184function returnMissingInt(): ?int { 185} 186 187try { 188 returnMissingInt(); 189} catch (\TypeError $e) { 190 echo $e, PHP_EOL; 191} 192 193?> 194--EXPECTF-- 195TypeError: unloadedClass(): Argument #1 ($param) must be of type ?I\Dont\Exist, stdClass given, called in %s:%d 196Stack trace: 197#0 %s(%d): unloadedClass(Object(stdClass)) 198#1 {main} 199TypeError: loadedClass(): Argument #1 ($param) must be of type ?RealClass, stdClass given, called in %s:%d 200Stack trace: 201#0 %s(%d): loadedClass(Object(stdClass)) 202#1 {main} 203TypeError: loadedInterface(): Argument #1 ($param) must be of type ?RealInterface, stdClass given, called in %s:%d 204Stack trace: 205#0 %s(%d): loadedInterface(Object(stdClass)) 206#1 {main} 207TypeError: unloadedClass(): Argument #1 ($param) must be of type ?I\Dont\Exist, int given, called in %s:%d 208Stack trace: 209#0 %s(%d): unloadedClass(1) 210#1 {main} 211TypeError: loadedClass(): Argument #1 ($param) must be of type ?RealClass, int given, called in %s:%d 212Stack trace: 213#0 %s(%d): loadedClass(1) 214#1 {main} 215TypeError: loadedInterface(): Argument #1 ($param) must be of type ?RealInterface, int given, called in %s:%d 216Stack trace: 217#0 %s(%d): loadedInterface(1) 218#1 {main} 219TypeError: callableF(): Argument #1 ($param) must be of type ?callable, int given, called in %s:%d 220Stack trace: 221#0 %s(%d): callableF(1) 222#1 {main} 223TypeError: intF(): Argument #1 ($param) must be of type ?int, stdClass given, called in %s:%d 224Stack trace: 225#0 %s(%d): intF(Object(stdClass)) 226#1 {main} 227TypeError: returnUnloadedClass(): Return value must be of type ?I\Dont\Exist, stdClass returned in %s:%d 228Stack trace: 229#0 %s(%d): returnUnloadedClass() 230#1 {main} 231TypeError: returnLoadedClass(): Return value must be of type ?RealClass, stdClass returned in %s:%d 232Stack trace: 233#0 %s(%d): returnLoadedClass() 234#1 {main} 235TypeError: returnLoadedInterface(): Return value must be of type ?RealInterface, stdClass returned in %s:%d 236Stack trace: 237#0 %s(%d): returnLoadedInterface() 238#1 {main} 239TypeError: returnUnloadedClassScalar(): Return value must be of type ?I\Dont\Exist, int returned in %s:%d 240Stack trace: 241#0 %s(%d): returnUnloadedClassScalar() 242#1 {main} 243TypeError: returnLoadedClassScalar(): Return value must be of type ?RealClass, int returned in %s:%d 244Stack trace: 245#0 %s(%d): returnLoadedClassScalar() 246#1 {main} 247TypeError: returnLoadedInterfaceScalar(): Return value must be of type ?RealInterface, int returned in %s:%d 248Stack trace: 249#0 %s(%d): returnLoadedInterfaceScalar() 250#1 {main} 251TypeError: returnCallable(): Return value must be of type ?callable, int returned in %s:%d 252Stack trace: 253#0 %s(%d): returnCallable() 254#1 {main} 255TypeError: returnInt(): Return value must be of type ?int, stdClass returned in %s:%d 256Stack trace: 257#0 %s(%d): returnInt() 258#1 {main} 259TypeError: returnMissingUnloadedClass(): Return value must be of type ?I\Dont\Exist, none returned in %s:%d 260Stack trace: 261#0 %s(%d): returnMissingUnloadedClass() 262#1 {main} 263TypeError: returnMissingLoadedClass(): Return value must be of type ?RealClass, none returned in %s:%d 264Stack trace: 265#0 %s(%d): returnMissingLoadedClass() 266#1 {main} 267TypeError: returnMissingLoadedInterface(): Return value must be of type ?RealInterface, none returned in %s:%d 268Stack trace: 269#0 %s(%d): returnMissingLoadedInterface() 270#1 {main} 271TypeError: returnMissingCallable(): Return value must be of type ?callable, none returned in %s:%d 272Stack trace: 273#0 %s(%d): returnMissingCallable() 274#1 {main} 275TypeError: returnMissingInt(): Return value must be of type ?int, none returned in %s:%d 276Stack trace: 277#0 %s(%d): returnMissingInt() 278#1 {main} 279