language/types/declarations.xml
e612d76529255bc8db91d0f87e5636e3a405dd38
...
...
@@ -10,130 +10,148 @@
10
10
<classname>TypeError</classname> is thrown.
11
11
</para>
12
12

13
-
<!-- Find better place where to put this note -->
13
+
<para>
14
+
Every single type that PHP supports, with the exception of
15
+
<type>resource</type> can be used within a user-land type declaration.
16
+
This page contains a changelog of availability of the different types
17
+
and documentation about usage of them in type declarations.
18
+
</para>
19
+

14
20
<note>
15
-
<!-- TODO Link to covariance section -->
16
21
<para>
17
-
When overriding a parent method, the child's method must match any return
18
-
type declaration on the parent. If the parent doesn't define a return
19
-
type, then the child method may do so.
22
+
When a class implements an interface method or reimplements a method which
23
+
has already been defined by a parent class, it has to be compatible with the
24
+
aforementioned definition.
25
+
A method is compatible if it follows the
26
+
<link linkend="language.oop5.variance">variance</link> rules.
20
27
</para>
21
28
</note>
22
29

23
-
<sect2 xml:id="language.types.declarations.base">
24
-
<title>Single types</title>
30
+
<sect2 role="changelog">
31
+
&reftitle.changelog;
25
32
<informaltable>
26
-
<tgroup cols="3">
33
+
<tgroup cols="2">
27
34
<thead>
28
35
<row>
29
-
<entry>&Type;</entry>
30
-
<entry>&Description;</entry>
31
36
<entry>&Version;</entry>
37
+
<entry>&Description;</entry>
32
38
</row>
33
39
</thead>
34
40
<tbody>
35
41
<row>
36
-
<entry>Class/interface name</entry>
42
+
<entry>8.3.0</entry>
43
+
<entry>
44
+
Support for class, interface, trait, and enum constant typing has been added.
45
+
</entry>
46
+
</row>
47
+
<row>
48
+
<entry>8.2.0</entry>
49
+
<entry>
50
+
Support for <acronym>DNF</acronym> types has been added.
51
+
</entry>
52
+
</row>
53
+
<row>
54
+
<entry>8.2.0</entry>
55
+
<entry>
56
+
Support for the literal type <type>true</type> has been added.
57
+
</entry>
58
+
</row>
59
+
<row>
60
+
<entry>8.2.0</entry>
37
61
<entry>
38
-
The value must be an &instanceof; the given class or interface.
62
+
The types <type>null</type> and <type>false</type> can now be used standalone.
39
63
</entry>
40
-
<entry/>
41
64
</row>
42
65
<row>
43
-
<entry><type>self</type></entry>
66
+
<entry>8.1.0</entry>
44
67
<entry>
45
-
The value must be an &instanceof; the same class as the one
46
-
in which the type declaration is used.
47
-
Can only be used in classes.
68
+
Support for intersection types has been added.
48
69
</entry>
49
-
<entry/>
50
70
</row>
51
71
<row>
52
-
<entry><type>parent</type></entry>
72
+
<entry>8.1.0</entry>
53
73
<entry>
54
-
The value must be an &instanceof; the parent of the class
55
-
in which the type declaration is used.
56
-
Can only be used in classes.
74
+
Returning by reference from a <type>void</type> function is now deprecated.
57
75
</entry>
58
-
<entry/>
59
76
</row>
60
77
<row>
61
-
<entry><type>array</type></entry>
78
+
<entry>8.1.0</entry>
62
79
<entry>
63
-
The value must be an <type>array</type>.
80
+
Support for the return only type <type>never</type> has been added.
64
81
</entry>
65
-
<entry/>
66
82
</row>
67
83
<row>
68
-
<entry><type>callable</type></entry>
84
+
<entry>8.0.0</entry>
69
85
<entry>
70
-
The value must be a valid <type>callable</type>.
71
-
Cannot be used as a class property type declaration.
86
+
Support for <type>mixed</type> has been added.
72
87
</entry>
73
-
<entry/>
74
88
</row>
75
89
<row>
76
-
<entry><type>bool</type></entry>
90
+
<entry>8.0.0</entry>
77
91
<entry>
78
-
The value must be a boolean value.
92
+
Support for the return only type <type>static</type> has been added.
79
93
</entry>
80
-
<entry/>
81
94
</row>
82
95
<row>
83
-
<entry><type>float</type></entry>
96
+
<entry>8.0.0</entry>
84
97
<entry>
85
-
The value must be a floating point number.
98
+
Support for union types has been added.
86
99
</entry>
87
-
<entry/>
88
100
</row>
89
101
<row>
90
-
<entry><type>int</type></entry>
102
+
<entry>7.4.0</entry>
91
103
<entry>
92
-
The value must be an integer.
104
+
Support for class properties typing has been added.
93
105
</entry>
94
-
<entry/>
95
106
</row>
96
107
<row>
97
-
<entry><type>string</type></entry>
108
+
<entry>7.2.0</entry>
98
109
<entry>
99
-
The value must be a <type>string</type>.
110
+
Support for <type>object</type> has been added.
100
111
</entry>
101
-
<entry/>
102
112
</row>
103
113
<row>
104
-
<entry><type>iterable</type></entry>
114
+
<entry>7.1.0</entry>
105
115
<entry>
106
-
The value must be either an <type>array</type> or an &instanceof; <classname>Traversable</classname>.
116
+
Support for <type>iterable</type> has been added.
107
117
</entry>
108
-
<entry>PHP 7.1.0</entry>
109
118
</row>
110
119
<row>
111
-
<entry><type>object</type></entry>
120
+
<entry>7.1.0</entry>
112
121
<entry>
113
-
The value must be an <type>object</type>.
122
+
Support for <type>void</type> has been added.
114
123
</entry>
115
-
<entry>PHP 7.2.0</entry>
116
124
</row>
117
125
<row>
118
-
<entry><type>mixed</type></entry>
126
+
<entry>7.1.0</entry>
119
127
<entry>
120
-
The value can be any value.
128
+
Support for nullable types has been added.
121
129
</entry>
122
-
<entry>PHP 8.0.0</entry>
123
130
</row>
124
131
</tbody>
125
132
</tgroup>
126
133
</informaltable>
134
+
</sect2>
127
135

128
-
<warning>
129
-
<para>
130
-
Aliases for the above scalar types are not supported.
131
-
Instead, they are treated as class or interface names.
132
-
For example, using <literal>boolean</literal> as a type declaration
133
-
will require the value to be an &instanceof; the class or interface
134
-
<literal>boolean</literal>, rather than of type <type>bool</type>:
135
-
</para>
136
-
<para>
136
+
<sect2 xml:id="language.types.declarations.base">
137
+
<title>Atomic Types Usage Notes</title>
138
+

139
+
<simpara>
140
+
Atomic types have straight forward behaviour with some minor caveats which
141
+
are described in this section.
142
+
</simpara>
143
+

144
+
<sect3 xml:id="language.types.declarations.base.scalar">
145
+
<title>Scalar types</title>
146
+
<warning>
147
+
<para>
148
+
Name aliases for scalar types (<type>bool</type>, <type>int</type>,
149
+
<type>float</type>, <type>string</type>) are not supported.
150
+
Instead, they are treated as class or interface names.
151
+
For example, using <literal>boolean</literal> as a type declaration
152
+
will require the value to be an &instanceof; the class or interface
153
+
<literal>boolean</literal>, rather than of type <type>bool</type>:
154
+
</para>
137
155
<example>
138
156
<programlisting role="php">
139
157
<![CDATA[
...
...
@@ -156,29 +174,296 @@ Stack trace:
156
174
]]>
157
175
</screen>
158
176
</example>
177
+
</warning>
178
+
</sect3>
179
+

180
+
<sect3 xml:id="language.types.declarations.void">
181
+
<title>void</title>
182
+
<note>
183
+
<para>
184
+
Returning by reference from a <type>void</type> function is deprecated as of PHP 8.1.0,
185
+
because such a function is contradictory.
186
+
Previously, it already emitted the following
187
+
<constant>E_NOTICE</constant> when called:
188
+
<computeroutput>Only variable references should be returned by reference</computeroutput>.
189
+
<informalexample>
190
+
<programlisting role="php">
191
+
<![CDATA[
192
+
<?php
193
+
function &test(): void {}
194
+
?>
195
+
]]>
196
+
</programlisting>
197
+
</informalexample>
198
+
</para>
199
+
</note>
200
+
</sect3>
201
+

202
+
<sect3 xml:id="language.types.declarations.base.function">
203
+
<title>Callable types</title>
204
+
<para>
205
+
This type cannot be used as a class property type declaration.
159
206
</para>
160
-
</warning>
161
207

162
-
<sect3 xml:id="language.types.declarations.mixed">
163
-
<title>mixed</title>
208
+
<note>
209
+
<simpara>
210
+
It is not possible to specify the signature of the function.
211
+
</simpara>
212
+
</note>
213
+
</sect3>
164
214

165
-
<para>
166
-
<type>mixed</type> is equivalent to the <link linkend="language.types.declarations.union">union type</link>
167
-
<type class="union">
168
-
<type>object</type><type>resource</type><type>array</type><type>string</type>
169
-
<type>int</type><type>float</type><type>bool</type><type>null</type>
170
-
</type>.
171
-
Available as of PHP 8.0.0.
172
-
</para>
173
-
</sect3>
215
+
<sect3 xml:id="language.types.declarations.references">
216
+
<title>Type declarations on pass-by-reference Parameters</title>
174
217

175
-
<sect3 xml:id="language.types.declarations.examples">
176
-
&reftitle.examples;
218
+
<simpara>
219
+
If a pass-by-reference parameter has a type declaration, the type of the
220
+
variable is <emphasis>only</emphasis> checked on function entry, at the
221
+
beginning of the call, but not when the function returns.
222
+
This means that a function can change the type of variable reference.
223
+
</simpara>
177
224
<example>
178
-
<title>Basic class type declaration</title>
225
+
<title>Typed pass-by-reference Parameters</title>
179
226
<programlisting role="php">
180
227
<![CDATA[
181
228
<?php
229
+
function array_baz(array &$param)
230
+
{
231
+
$param = 1;
232
+
}
233
+
$var = [];
234
+
array_baz($var);
235
+
var_dump($var);
236
+
array_baz($var);
237
+
?>
238
+
]]>
239
+
</programlisting>
240
+
&example.outputs.similar;
241
+
<screen>
242
+
<![CDATA[
243
+
int(1)
244
+

245
+
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
246
+
Stack trace:
247
+
#0 -(9): array_baz(1)
248
+
#1 {main}
249
+
thrown in - on line 2
250
+
]]>
251
+
</screen>
252
+
</example>
253
+
</sect3>
254
+
</sect2>
255
+

256
+
<sect2 xml:id="language.types.declarations.composite">
257
+
<title>Composite Types Usage Notes</title>
258
+
<para>
259
+
Composite type declarations are subject to a couple of restrictions and
260
+
will perform a redundancy check at compile time to prevent simple bugs.
261
+
</para>
262
+

263
+
<caution>
264
+
<simpara>
265
+
Prior to PHP 8.2.0, and the introduction of <acronym>DNF</acronym> types,
266
+
it was not possible to combine intersection types with union types.
267
+
</simpara>
268
+
</caution>
269
+

270
+
<sect3 xml:id="language.types.declarations.composite.union">
271
+
<title>Union types</title>
272
+
<warning>
273
+
<simpara>
274
+
It is not possible to combine the two value types <type>false</type>
275
+
and <type>true</type> together in a union type.
276
+
Use <type>bool</type> instead.
277
+
</simpara>
278
+
</warning>
279
+

280
+
<caution>
281
+
<simpara>
282
+
Prior to PHP 8.2.0, as <type>false</type> and <type>null</type>
283
+
could not be used as standalone types, a union type comprised of only
284
+
these types was not permitted. This comprises the following types:
285
+
<type>false</type>, <literal>false|null</literal>,
286
+
and <literal>?false</literal>.
287
+
</simpara>
288
+
</caution>
289
+

290
+
<sect4 xml:id="language.types.declarations.nullable">
291
+
<title>Nullable type syntactic sugar</title>
292
+

293
+
<para>
294
+
A single base type declaration can be marked nullable by prefixing the
295
+
type with a question mark (<literal>?</literal>).
296
+
Thus <literal>?T</literal> and <literal>T|null</literal> are identical.
297
+
</para>
298
+

299
+
<note>
300
+
<simpara>
301
+
This syntax is supported as of PHP 7.1.0, and predates generalized union
302
+
types support.
303
+
</simpara>
304
+
</note>
305
+

306
+
<note>
307
+
<para>
308
+
It is also possible to achieve nullable arguments by making
309
+
<literal>null</literal> the default value.
310
+
This is not recommended as if the default value is changed in a child
311
+
class a type compatibility violation will be raised as the
312
+
<type>null</type> type will need to be added to the type declaration.
313
+
</para>
314
+
<example>
315
+
<title>Old way to make arguments nullable</title>
316
+
<programlisting role="php">
317
+
<![CDATA[
318
+
<?php
319
+
class C {}
320
+

321
+
function f(C $c = null) {
322
+
var_dump($c);
323
+
}
324
+

325
+
f(new C);
326
+
f(null);
327
+
?>
328
+
]]>
329
+
</programlisting>
330
+
&example.outputs;
331
+
<screen>
332
+
<![CDATA[
333
+
object(C)#1 (0) {
334
+
}
335
+
NULL
336
+
]]>
337
+
</screen>
338
+
</example>
339
+
</note>
340
+
</sect4>
341
+
</sect3>
342
+

343
+
<sect3 xml:id="language.types.declarations.composite.redundant">
344
+
<title>Duplicate and redundant types</title>
345
+
<para>
346
+
To catch simple bugs in composite type declarations, redundant types that
347
+
can be detected without performing class loading will result in a
348
+
compile-time error. This includes:
349
+

350
+
<itemizedlist>
351
+
<listitem>
352
+
<simpara>
353
+
Each name-resolved type may only occur once. Types such as
354
+
<literal>int|string|INT</literal> or
355
+
<literal>Countable&amp;Traversable&amp;COUNTABLE</literal>
356
+
result in an error.
357
+
</simpara>
358
+
</listitem>
359
+
<listitem>
360
+
<simpara>
361
+
Using <type>mixed</type> results in an error.
362
+
</simpara>
363
+
</listitem>
364
+
<listitem>
365
+
<simpara>For union types:</simpara>
366
+
<itemizedlist>
367
+
<listitem>
368
+
<simpara>
369
+
If <type>bool</type> is used, <type>false</type> or <type>true</type>
370
+
cannot be used additionally.
371
+
</simpara>
372
+
</listitem>
373
+
<listitem>
374
+
<simpara>
375
+
If <type>object</type> is used, class types cannot be used additionally.
376
+
</simpara>
377
+
</listitem>
378
+
<listitem>
379
+
<simpara>
380
+
If <type>iterable</type> is used, <type>array</type>
381
+
and <classname>Traversable</classname> cannot be used additionally.
382
+
</simpara>
383
+
</listitem>
384
+
</itemizedlist>
385
+
</listitem>
386
+
<listitem>
387
+
<simpara>For intersection types:</simpara>
388
+
<itemizedlist>
389
+
<listitem>
390
+
<simpara>
391
+
Using a type which is not a class-type results in an error.
392
+
</simpara>
393
+
</listitem>
394
+
<listitem>
395
+
<simpara>
396
+
Using either <type>self</type>, <type>parent</type>, or
397
+
<type>static</type> results in an error.
398
+
</simpara>
399
+
</listitem>
400
+
</itemizedlist>
401
+
</listitem>
402
+
<listitem>
403
+
<simpara>For <acronym>DNF</acronym> types:</simpara>
404
+
<itemizedlist>
405
+
<listitem>
406
+
<simpara>
407
+
If a more generic type is used, the more restrictive one is redundant.
408
+
</simpara>
409
+
</listitem>
410
+
<listitem>
411
+
<simpara>
412
+
Using two identical intersection types.
413
+
</simpara>
414
+
</listitem>
415
+
</itemizedlist>
416
+
</listitem>
417
+
</itemizedlist>
418
+
</para>
419
+

420
+
<note>
421
+
<simpara>
422
+
This does not guarantee that the type is “minimal”, because doing so would
423
+
require loading all used class types.
424
+
</simpara>
425
+
</note>
426
+

427
+
<para>
428
+
For example, if <literal>A</literal> and <literal>B</literal> are class
429
+
aliases, then <literal>A|B</literal> remains a legal union type, even
430
+
though it could be reduced to either <literal>A</literal> or
431
+
<literal>B</literal>.
432
+
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
433
+
is also a legal union type, even though it could be reduced to just
434
+
<literal>A</literal>.
435
+

436
+
<informalexample>
437
+
<programlisting role="php">
438
+
<![CDATA[
439
+
<?php
440
+
function foo(): int|INT {} // Disallowed
441
+
function foo(): bool|false {} // Disallowed
442
+
function foo(): int&Traversable {} // Disallowed
443
+
function foo(): self&Traversable {} // Disallowed
444
+

445
+
use A as B;
446
+
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
447
+
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
448
+

449
+
class_alias('X', 'Y');
450
+
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
451
+
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
452
+
?>
453
+
]]>
454
+
</programlisting>
455
+
</informalexample>
456
+
</para>
457
+
</sect3>
458
+
</sect2>
459
+

460
+
<sect2 xml:id="language.types.declarations.examples">
461
+
&reftitle.examples;
462
+
<example>
463
+
<title>Basic class type declaration</title>
464
+
<programlisting role="php">
465
+
<![CDATA[
466
+
<?php
182
467
class C {}
183
468
class D extends C {}
184
469

...
...
@@ -194,9 +479,9 @@ f(new D);
194
479
f(new E);
195
480
?>
196
481
]]>
197
-
</programlisting>
198
-
&example.outputs.8;
199
-
<screen>
482
+
</programlisting>
483
+
&example.outputs.8;
484
+
<screen>
200
485
<![CDATA[
201
486
C
202
487
D
...
...
@@ -207,12 +492,12 @@ Stack trace:
207
492
#1 {main}
208
493
thrown in - on line 8
209
494
]]>
210
-
</screen>
211
-
</example>
495
+
</screen>
496
+
</example>
212
497

213
-
<example>
214
-
<title>Basic interface type declaration</title>
215
-
<programlisting role="php">
498
+
<example>
499
+
<title>Basic interface type declaration</title>
500
+
<programlisting role="php">
216
501
<![CDATA[
217
502
<?php
218
503
interface I { public function f(); }
...
...
@@ -229,9 +514,9 @@ f(new C);
229
514
f(new E);
230
515
?>
231
516
]]>
232
-
</programlisting>
233
-
&example.outputs.8;
234
-
<screen>
517
+
</programlisting>
518
+
&example.outputs.8;
519
+
<screen>
235
520
<![CDATA[
236
521
C
237
522

...
...
@@ -241,12 +526,12 @@ Stack trace:
241
526
#1 {main}
242
527
thrown in - on line 8
243
528
]]>
244
-
</screen>
245
-
</example>
529
+
</screen>
530
+
</example>
246
531

247
-
<example>
248
-
<title>Basic return type declaration</title>
249
-
<programlisting role="php">
532
+
<example>
533
+
<title>Basic return type declaration</title>
534
+
<programlisting role="php">
250
535
<![CDATA[
251
536
<?php
252
537
function sum($a, $b): float {
...
...
@@ -257,18 +542,18 @@ function sum($a, $b): float {
257
542
var_dump(sum(1, 2));
258
543
?>
259
544
]]>
260
-
</programlisting>
261
-
&example.outputs;
262
-
<screen>
545
+
</programlisting>
546
+
&example.outputs;
547
+
<screen>
263
548
<![CDATA[
264
549
float(3)
265
550
]]>
266
-
</screen>
267
-
</example>
551
+
</screen>
552
+
</example>
268
553

269
-
<example>
270
-
<title>Returning an object</title>
271
-
<programlisting role="php">
554
+
<example>
555
+
<title>Returning an object</title>
556
+
<programlisting role="php">
272
557
<![CDATA[
273
558
<?php
274
559
class C {}
...
...
@@ -280,32 +565,20 @@ function getC(): C {
280
565
var_dump(getC());
281
566
?>
282
567
]]>
283
-
</programlisting>
284
-
&example.outputs;
285
-
<screen>
568
+
</programlisting>
569
+
&example.outputs;
570
+
<screen>
286
571
<![CDATA[
287
572
object(C)#1 (0) {
288
573
}
289
574
]]>
290
-
</screen>
291
-
</example>
292
-
</sect3>
293
-
</sect2>
294
-

295
-
<sect2 xml:id="language.types.declarations.nullable">
296
-
<title>Nullable type</title>
297
-

298
-
<para>
299
-
As of PHP 7.1.0, type declarations can be marked nullable by prefixing the
300
-
type name with a question mark (<literal>?</literal>).
301
-
This signifies that the value can be of the specified type or &null;.
302
-
</para>
575
+
</screen>
576
+
</example>
303
577

304
-
<para>
305
-
<example>
306
-
<title>Nullable argument type declaration</title>
307
-
<programlisting role="php">
308
-
<![CDATA[
578
+
<example>
579
+
<title>Nullable argument type declaration</title>
580
+
<programlisting role="php">
581
+
<![CDATA[
309
582
<?php
310
583
class C {}
311
584

...
...
@@ -317,21 +590,21 @@ f(new C);
317
590
f(null);
318
591
?>
319
592
]]>
320
-
</programlisting>
321
-
&example.outputs;
322
-
<screen>
323
-
<![CDATA[
593
+
</programlisting>
594
+
&example.outputs;
595
+
<screen>
596
+
<![CDATA[
324
597
object(C)#1 (0) {
325
598
}
326
599
NULL
327
600
]]>
328
-
</screen>
329
-
</example>
601
+
</screen>
602
+
</example>
330
603

331
-
<example>
332
-
<title>Nullable return type declaration</title>
333
-
<programlisting role="php">
334
-
<![CDATA[
604
+
<example>
605
+
<title>Nullable return type declaration</title>
606
+
<programlisting role="php">
607
+
<![CDATA[
335
608
<?php
336
609
function get_item(): ?string {
337
610
if (isset($_GET['item'])) {
...
...
@@ -342,203 +615,32 @@ function get_item(): ?string {
342
615
}
343
616
?>
344
617
]]>
345
-
</programlisting>
346
-
</example>
347
-
</para>
618
+
</programlisting>
619
+
</example>
348
620

349
-
<note>
350
-
<para>
351
-
Prior to PHP 7.1.0, it was possible to achieve nullable arguments by making
352
-
<literal>null</literal> the default value.
353
-
This is not recommended as this breaks during inheritance.
354
-
</para>
355
-
<example>
356
-
<title>Old way to make arguments nullable</title>
357
-
<programlisting role="php">
621
+
<example>
622
+
<title>Class property type declaration</title>
623
+
<programlisting role="php">
358
624
<![CDATA[
359
625
<?php
360
-
class C {}
626
+
class User {
627
+
public static string $foo = 'foo';
361
628

362
-
function f(C $c = null) {
363
-
var_dump($c);
364
-
}
629
+
public int $id;
630
+
public string $username;
365
631

366
-
f(new C);
367
-
f(null);
368
-
?>
369
-
]]>
370
-
</programlisting>
371
-
&example.outputs;
372
-
<screen>
373
-
<![CDATA[
374
-
object(C)#1 (0) {
632
+
public function __construct(int $id, string $username) {
633
+
$this->id = $id;
634
+
$this->username = $username;
635
+
}
375
636
}
376
-
NULL
377
-
]]>
378
-
</screen>
379
-
</example>
380
-
</note>
381
-
</sect2>
382
-

383
-
<sect2 xml:id="language.types.declarations.union">
384
-
<title>Union types</title>
385
-
<para>
386
-
A union type declaration accepts values of multiple different types,
387
-
rather than a single one.
388
-
Union types are specified using the syntax <literal>T1|T2|...</literal>.
389
-
Union types are available as of PHP 8.0.0.
390
-
</para>
391
-

392
-
<sect3 xml:id="language.types.declarations.union.nullable">
393
-
<title>Nullable union types</title>
394
-
<para>
395
-
The <literal>null</literal> type is supported as part of unions,
396
-
such that <literal>T1|T2|null</literal> can be used to create a nullable union.
397
-
The existing <literal>?T</literal> notation is considered a shorthand
398
-
for the common case of <literal>T|null</literal>.
399
-
</para>
400
-

401
-
<caution>
402
-
<simpara>
403
-
<literal>null</literal> cannot be used as a standalone type.
404
-
</simpara>
405
-
</caution>
406
-
</sect3>
407
-

408
-
<sect3 xml:id="language.types.declarations.union.false">
409
-
<title>false pseudo-type</title>
410
-
<para>
411
-
The <literal>false</literal> literal type is supported as part of unions,
412
-
and is included as for historical reasons many internal functions return
413
-
<literal>false</literal> instead of <literal>null</literal> for failures.
414
-
A classic example of such a function is <function>strpos</function>.
415
-
</para>
416
-

417
-
<caution>
418
-
<simpara>
419
-
<literal>false</literal> cannot be used as a standalone type (including
420
-
nullable standalone type).
421
-
As such, all of <literal>false</literal>, <literal>false|null</literal>
422
-
and <literal>?false</literal> are not permitted.
423
-
</simpara>
424
-
</caution>
425
-
<caution>
426
-
<simpara>
427
-
The <literal>true</literal> literal type does <emphasis>not</emphasis>
428
-
exist.
429
-
</simpara>
430
-
</caution>
431
-
</sect3>
432
-

433
-
<sect3 xml:id="language.types.declarations.union.redundant">
434
-
<title>Duplicate and redundant types</title>
435
-
<para>
436
-
To catch simple bugs in union type declarations, redundant types that
437
-
can be detected without performing class loading will result in a
438
-
compile-time error. This includes:
439
-

440
-
<itemizedlist>
441
-
<listitem>
442
-
<simpara>
443
-
Each name-resolved type may only occur once. Types such as
444
-
<literal>int|string|INT</literal> result in an error.
445
-
</simpara>
446
-
</listitem>
447
-
<listitem>
448
-
<simpara>
449
-
If <type>bool</type> is used, <type>false</type> cannot be used additionally.
450
-
</simpara>
451
-
</listitem>
452
-
<listitem>
453
-
<simpara>
454
-
If <type>object</type> is used, class types cannot be used additionally.
455
-
</simpara>
456
-
</listitem>
457
-
<listitem>
458
-
<simpara>
459
-
If <type>iterable</type> is used, <type>array</type>
460
-
and <classname>Traversable</classname> cannot be used additionally.
461
-
</simpara>
462
-
</listitem>
463
-
</itemizedlist>
464
-
</para>
465
-

466
-
<note>
467
-
<simpara>
468
-
This does not guarantee that the type is “minimal”, because doing so would
469
-
require loading all used class types.
470
-
</simpara>
471
-
</note>
472
-

473
-
<para>
474
-
For example, if <literal>A</literal> and <literal>B</literal> are class
475
-
aliases, then <literal>A|B</literal> remains a legal union type, even
476
-
though it could be reduced to either <literal>A</literal> or
477
-
<literal>B</literal>.
478
-
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
479
-
is also a legal union type, even though it could be reduced to just
480
-
<literal>A</literal>.
481
-

482
-
<informalexample>
483
-
<programlisting role="php">
484
-
<![CDATA[
485
-
<?php
486
-
function foo(): int|INT {} // Disallowed
487
-
function foo(): bool|false {} // Disallowed
488
-

489
-
use A as B;
490
-
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
491
-

492
-
class_alias('X', 'Y');
493
-
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
494
637
?>
495
638
]]>
496
-
</programlisting>
497
-
</informalexample>
498
-
</para>
499
-
</sect3>
500
-

501
-
</sect2>
502
-

503
-
<sect2 xml:id="language.types.declarations.return-only">
504
-
<title>Return only types</title>
505
-

506
-
<sect3 xml:id="language.types.declarations.void">
507
-
<title>void</title>
508
-
<para>
509
-
<literal>void</literal> is a return type indicating the function does not
510
-
return a value.
511
-
Therefore it cannot be part of a union type declaration.
512
-
Available as of PHP 7.1.0.
513
-
</para>
514
-
</sect3>
515
-

516
-
<sect3 xml:id="language.types.declarations.never">
517
-
<title>never</title>
518
-
<para>
519
-
<literal>never</literal> is a return type indicating the function does not
520
-
return. This means that it either calls <function>exit</function>, throws
521
-
an exception, or is an infinite loop.
522
-
Therefore it cannot be part of a union type declaration.
523
-
Available as of PHP 8.1.0.
524
-
</para>
525
-
<para>
526
-
<type>never</type> is, in type theory parlance, the bottom type.
527
-
Meaning it is the subtype of every other type and can replace any other
528
-
return type during inheritance.
529
-
</para>
530
-
</sect3>
531
-

532
-
<sect3 xml:id="language.types.declarations.static">
533
-
<title>static</title>
534
-
<para>
535
-
The value must be an &instanceof; the same class as the one the
536
-
method is called in.
537
-
Available as of PHP 8.0.0.
538
-
</para>
539
-
</sect3>
639
+
</programlisting>
640
+
</example>
540
641
</sect2>
541
642

643
+
<!-- TODO Move this into its own declare page -->
542
644
<sect2 xml:id="language.types.declarations.strict">
543
645
<title>Strict typing</title>
544
646

...
...
@@ -672,161 +774,7 @@ Stack trace:
672
774
</example>
673
775
</sect2>
674
776

675
-
<sect2 xml:id="language.types.declarations.union.coercive">
676
-
<title>Coercive typing with union types</title>
677
-
<para>
678
-
When <literal>strict_types</literal> is not enabled, scalar type declarations
679
-
are subject to limited implicit type coercions.
680
-
If the exact type of the value is not part of the union, then the target type
681
-
is chosen in the following order of preference:
682
-

683
-
<orderedlist>
684
-
<listitem>
685
-
<simpara>
686
-
<type>int</type>
687
-
</simpara>
688
-
</listitem>
689
-
<listitem>
690
-
<simpara>
691
-
<type>float</type>
692
-
</simpara>
693
-
</listitem>
694
-
<listitem>
695
-
<simpara>
696
-
<type>string</type>
697
-
</simpara>
698
-
</listitem>
699
-
<listitem>
700
-
<simpara>
701
-
<type>bool</type>
702
-
</simpara>
703
-
</listitem>
704
-
</orderedlist>
705
-

706
-
If the type both exists in the union, and the value can be coerced to the
707
-
type under PHPs existing type checking semantics, then the type is chosen.
708
-
Otherwise the next type is tried.
709
-
</para>
710
-

711
-
<caution>
712
-
<para>
713
-
As an exception, if the value is a string and both int and float are part
714
-
of the union, the preferred type is determined by the existing
715
-
“numeric string” semantics.
716
-
For example, for <literal>"42"</literal> <type>int</type> is chosen,
717
-
while for <literal>"42.0"</literal> <type>float</type> is chosen.
718
-
</para>
719
-
</caution>
720
-

721
-
<note>
722
-
<para>
723
-
Types that are not part of the above preference list are not eligible
724
-
targets for implicit coercion. In particular no implicit coercions to
725
-
the <literal>null</literal> and <literal>false</literal> types occur.
726
-
</para>
727
-
</note>
728
-

729
-
<example>
730
-
<title>Example of types being coerced into a type part of the union</title>
731
-
<programlisting role="php">
732
-
<![CDATA[
733
-
<?php
734
-
// int|string
735
-
42 --> 42 // exact type
736
-
"42" --> "42" // exact type
737
-
new ObjectWithToString --> "Result of __toString()"
738
-
// object never compatible with int, fall back to string
739
-
42.0 --> 42 // float compatible with int
740
-
42.1 --> 42 // float compatible with int
741
-
1e100 --> "1.0E+100" // float too large for int type, fall back to string
742
-
INF --> "INF" // float too large for int type, fall back to string
743
-
true --> 1 // bool compatible with int
744
-
[] --> TypeError // array not compatible with int or string
745
-

746
-
// int|float|bool
747
-
"45" --> 45 // int numeric string
748
-
"45.0" --> 45.0 // float numeric string
749
-

750
-
"45X" --> true // not numeric string, fall back to bool
751
-
"" --> false // not numeric string, fall back to bool
752
-
"X" --> true // not numeric string, fall back to bool
753
-
[] --> TypeError // array not compatible with int, float or bool
754
-
?>
755
-
]]>
756
-
</programlisting>
757
-
</example>
758
-
</sect2>
759
-

760
-
<!-- TODO figure out what do to with these things -->
761
-
<sect2 xml:id="language.types.declarations.misc">
762
-
<title>Misc</title>
763
-
<example>
764
-
<title>Typed pass-by-reference Parameters</title>
765
-
<simpara>
766
-
Declared types of reference parameters are checked on function entry, but
767
-
not when the function returns, so after the function had returned, the
768
-
argument's type may have changed.
769
-
</simpara>
770
-
<programlisting role="php">
771
-
<![CDATA[
772
-
<?php
773
-
function array_baz(array &$param)
774
-
{
775
-
$param = 1;
776
-
}
777
-
$var = [];
778
-
array_baz($var);
779
-
var_dump($var);
780
-
array_baz($var);
781
-
?>
782
-
]]>
783
-
</programlisting>
784
-
&example.outputs.8;
785
-
<screen>
786
-
<![CDATA[
787
-
int(1)
788
-

789
-
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
790
-
Stack trace:
791
-
#0 -(9): array_baz(1)
792
-
#1 {main}
793
-
thrown in - on line 2
794
-
]]>
795
-
</screen>
796
-
</example>
797
-

798
-
<example>
799
-
<title>Catching <classname>TypeError</classname></title>
800
-
<programlisting role="php">
801
-
<![CDATA[
802
-
<?php
803
-
declare(strict_types=1);
804
-

805
-
function sum(int $a, int $b) {
806
-
return $a + $b;
807
-
}
808
-

809
-
try {
810
-
var_dump(sum(1, 2));
811
-
var_dump(sum(1.5, 2.5));
812
-
} catch (TypeError $e) {
813
-
echo 'Error: ', $e->getMessage();
814
-
}
815
-
?>
816
-
]]>
817
-
</programlisting>
818
-
&example.outputs.8;
819
-
<screen>
820
-
<![CDATA[
821
-
int(3)
822
-
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
823
-
]]>
824
-
</screen>
825
-
</example>
826
-
</sect2>
827
-

828
777
</sect1>
829
-

830
778
<!-- Keep this comment at the end of the file
831
779
Local variables:
832
780
mode: sgml
833
781