xref: /php-src/Zend/tests/typehints/or_null.phpt (revision b40ae808)
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