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 iterableF(?iterable $param) {} 61 62try { 63 iterableF(1); 64} catch (\TypeError $e) { 65 echo $e, PHP_EOL; 66} 67 68function intF(?int $param) {} 69 70try { 71 intF(new StdClass); 72} catch (\TypeError $e) { 73 echo $e, PHP_EOL; 74} 75 76function returnUnloadedClass(): ?I\Dont\Exist { 77 return new \StdClass; 78} 79 80try { 81 returnUnloadedClass(); 82} catch (\TypeError $e) { 83 echo $e, PHP_EOL; 84} 85 86function returnLoadedClass(): ?RealClass { 87 return new \StdClass; 88} 89 90try { 91 returnLoadedClass(); 92} catch (\TypeError $e) { 93 echo $e, PHP_EOL; 94} 95 96function returnLoadedInterface(): ?RealInterface { 97 return new \StdClass; 98} 99 100try { 101 returnLoadedInterface(); 102} catch (\TypeError $e) { 103 echo $e, PHP_EOL; 104} 105 106function returnUnloadedClassScalar(): ?I\Dont\Exist { 107 return 1; 108} 109 110try { 111 returnUnloadedClassScalar(); 112} catch (\TypeError $e) { 113 echo $e, PHP_EOL; 114} 115 116function returnLoadedClassScalar(): ?RealClass { 117 return 1; 118} 119 120try { 121 returnLoadedClassScalar(); 122} catch (\TypeError $e) { 123 echo $e, PHP_EOL; 124} 125 126function returnLoadedInterfaceScalar(): ?RealInterface { 127 return 1; 128} 129 130try { 131 returnLoadedInterfaceScalar(); 132} catch (\TypeError $e) { 133 echo $e, PHP_EOL; 134} 135 136function returnCallable(): ?callable { 137 return 1; 138} 139 140try { 141 returnCallable(); 142} catch (\TypeError $e) { 143 echo $e, PHP_EOL; 144} 145 146function returnIterable(): ?iterable { 147 return 1; 148} 149 150try { 151 returnIterable(); 152} catch (\TypeError $e) { 153 echo $e, PHP_EOL; 154} 155 156function returnInt(): ?int { 157 return new \StdClass; 158} 159 160try { 161 returnInt(); 162} catch (\TypeError $e) { 163 echo $e, PHP_EOL; 164} 165 166function returnMissingUnloadedClass(): ?I\Dont\Exist { 167} 168 169try { 170 returnMissingUnloadedClass(); 171} catch (\TypeError $e) { 172 echo $e, PHP_EOL; 173} 174 175function returnMissingLoadedClass(): ?RealClass { 176} 177 178try { 179 returnMissingLoadedClass(); 180} catch (\TypeError $e) { 181 echo $e, PHP_EOL; 182} 183 184function returnMissingLoadedInterface(): ?RealInterface { 185} 186 187try { 188 returnMissingLoadedInterface(); 189} catch (\TypeError $e) { 190 echo $e, PHP_EOL; 191} 192 193function returnMissingCallable(): ?callable { 194} 195 196try { 197 returnMissingCallable(); 198} catch (\TypeError $e) { 199 echo $e, PHP_EOL; 200} 201 202function returnMissingIterable(): ?iterable { 203} 204 205try { 206 returnMissingIterable(); 207} catch (\TypeError $e) { 208 echo $e, PHP_EOL; 209} 210 211function returnMissingInt(): ?int { 212} 213 214try { 215 returnMissingInt(); 216} catch (\TypeError $e) { 217 echo $e, PHP_EOL; 218} 219 220?> 221--EXPECTF-- 222TypeError: unloadedClass(): Argument #1 ($param) must be of type ?I\Dont\Exist, stdClass given, called in %s:%d 223Stack trace: 224#0 %s(8): unloadedClass(Object(stdClass)) 225#1 {main} 226TypeError: loadedClass(): Argument #1 ($param) must be of type ?RealClass, stdClass given, called in %s:%d 227Stack trace: 228#0 %s(20): loadedClass(Object(stdClass)) 229#1 {main} 230TypeError: loadedInterface(): Argument #1 ($param) must be of type ?RealInterface, stdClass given, called in %s:%d 231Stack trace: 232#0 %s(26): loadedInterface(Object(stdClass)) 233#1 {main} 234TypeError: unloadedClass(): Argument #1 ($param) must be of type ?I\Dont\Exist, int given, called in %s:%d 235Stack trace: 236#0 %s(32): unloadedClass(1) 237#1 {main} 238TypeError: loadedClass(): Argument #1 ($param) must be of type ?RealClass, int given, called in %s:%d 239Stack trace: 240#0 %s(38): loadedClass(1) 241#1 {main} 242TypeError: loadedInterface(): Argument #1 ($param) must be of type ?RealInterface, int given, called in %s:%d 243Stack trace: 244#0 %s(44): loadedInterface(1) 245#1 {main} 246TypeError: callableF(): Argument #1 ($param) must be of type ?callable, int given, called in %s:%d 247Stack trace: 248#0 %s(52): callableF(1) 249#1 {main} 250TypeError: iterableF(): Argument #1 ($param) must be of type ?iterable, int given, called in %s:%d 251Stack trace: 252#0 %s(60): iterableF(1) 253#1 {main} 254TypeError: intF(): Argument #1 ($param) must be of type ?int, stdClass given, called in %s:%d 255Stack trace: 256#0 %s(68): intF(Object(stdClass)) 257#1 {main} 258TypeError: returnUnloadedClass(): Return value must be of type ?I\Dont\Exist, stdClass returned in %s:%d 259Stack trace: 260#0 %s(78): returnUnloadedClass() 261#1 {main} 262TypeError: returnLoadedClass(): Return value must be of type ?RealClass, stdClass returned in %s:%d 263Stack trace: 264#0 %s(88): returnLoadedClass() 265#1 {main} 266TypeError: returnLoadedInterface(): Return value must be of type ?RealInterface, stdClass returned in %s:%d 267Stack trace: 268#0 %s(98): returnLoadedInterface() 269#1 {main} 270TypeError: returnUnloadedClassScalar(): Return value must be of type ?I\Dont\Exist, int returned in %s:%d 271Stack trace: 272#0 %s(108): returnUnloadedClassScalar() 273#1 {main} 274TypeError: returnLoadedClassScalar(): Return value must be of type ?RealClass, int returned in %s:%d 275Stack trace: 276#0 %s(118): returnLoadedClassScalar() 277#1 {main} 278TypeError: returnLoadedInterfaceScalar(): Return value must be of type ?RealInterface, int returned in %s:%d 279Stack trace: 280#0 %s(128): returnLoadedInterfaceScalar() 281#1 {main} 282TypeError: returnCallable(): Return value must be of type ?callable, int returned in %s:%d 283Stack trace: 284#0 %s(138): returnCallable() 285#1 {main} 286TypeError: returnIterable(): Return value must be of type ?iterable, int returned in %s:%d 287Stack trace: 288#0 %s(148): returnIterable() 289#1 {main} 290TypeError: returnInt(): Return value must be of type ?int, stdClass returned in %s:%d 291Stack trace: 292#0 %s(158): returnInt() 293#1 {main} 294TypeError: returnMissingUnloadedClass(): Return value must be of type ?I\Dont\Exist, none returned in %s:%d 295Stack trace: 296#0 %s(167): returnMissingUnloadedClass() 297#1 {main} 298TypeError: returnMissingLoadedClass(): Return value must be of type ?RealClass, none returned in %s:%d 299Stack trace: 300#0 %s(176): returnMissingLoadedClass() 301#1 {main} 302TypeError: returnMissingLoadedInterface(): Return value must be of type ?RealInterface, none returned in %s:%d 303Stack trace: 304#0 %s(185): returnMissingLoadedInterface() 305#1 {main} 306TypeError: returnMissingCallable(): Return value must be of type ?callable, none returned in %s:%d 307Stack trace: 308#0 %s(194): returnMissingCallable() 309#1 {main} 310TypeError: returnMissingIterable(): Return value must be of type ?iterable, none returned in %s:%d 311Stack trace: 312#0 %s(203): returnMissingIterable() 313#1 {main} 314TypeError: returnMissingInt(): Return value must be of type ?int, none returned in %s:%d 315Stack trace: 316#0 %s(212): returnMissingInt() 317#1 {main} 318