xref: /PHP-8.1/Zend/tests/typehints/or_null.phpt (revision fbe30592)
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