language/types/declarations.xml
e612d76529255bc8db91d0f87e5636e3a405dd38
...
...
@@ -10,122 +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>
61
+
<entry>
62
+
The types <type>null</type> and <type>false</type> can now be used standalone.
63
+
</entry>
64
+
</row>
65
+
<row>
66
+
<entry>8.1.0</entry>
37
67
<entry>
38
-
The value must be an &instanceof; the given class or interface.
68
+
Support for intersection types has been added.
39
69
</entry>
40
-
<entry></entry>
41
70
</row>
42
71
<row>
43
-
<entry><type>self</type></entry>
72
+
<entry>8.1.0</entry>
44
73
<entry>
45
-
The value must be an &instanceof; the same class as the one the
46
-
method is defined on.
47
-
Can only be used in classes.
74
+
Returning by reference from a <type>void</type> function is now deprecated.
48
75
</entry>
49
-
<entry></entry>
50
76
</row>
51
77
<row>
52
-
<entry><type>array</type></entry>
78
+
<entry>8.1.0</entry>
53
79
<entry>
54
-
The value must be an <type>array</type>.
80
+
Support for the return only type <type>never</type> has been added.
55
81
</entry>
56
-
<entry></entry>
57
82
</row>
58
83
<row>
59
-
<entry><type>callable</type></entry>
84
+
<entry>8.0.0</entry>
60
85
<entry>
61
-
The value must be a valid <type>callable</type>.
62
-
Cannot be used as a class property type declaration.
86
+
Support for <type>mixed</type> has been added.
63
87
</entry>
64
-
<entry></entry>
65
88
</row>
66
89
<row>
67
-
<entry><type>bool</type></entry>
90
+
<entry>8.0.0</entry>
68
91
<entry>
69
-
The value must be a boolean value.
92
+
Support for the return only type <type>static</type> has been added.
70
93
</entry>
71
-
<entry></entry>
72
94
</row>
73
95
<row>
74
-
<entry><type>float</type></entry>
96
+
<entry>8.0.0</entry>
75
97
<entry>
76
-
The value must be a floating point number.
98
+
Support for union types has been added.
77
99
</entry>
78
-
<entry></entry>
79
100
</row>
80
101
<row>
81
-
<entry><type>int</type></entry>
102
+
<entry>7.4.0</entry>
82
103
<entry>
83
-
The value must be an integer.
104
+
Support for class properties typing has been added.
84
105
</entry>
85
-
<entry></entry>
86
106
</row>
87
107
<row>
88
-
<entry><type>string</type></entry>
108
+
<entry>7.2.0</entry>
89
109
<entry>
90
-
The value must be a <type>string</type>.
110
+
Support for <type>object</type> has been added.
91
111
</entry>
92
-
<entry></entry>
93
112
</row>
94
113
<row>
95
-
<entry><type>iterable</type></entry>
114
+
<entry>7.1.0</entry>
96
115
<entry>
97
-
The value must be either an <type>array</type> or an &instanceof; <classname>Traversable</classname>.
116
+
Support for <type>iterable</type> has been added.
98
117
</entry>
99
-
<entry>PHP 7.1.0</entry>
100
118
</row>
101
119
<row>
102
-
<entry><type>object</type></entry>
120
+
<entry>7.1.0</entry>
103
121
<entry>
104
-
The value must be an <type>object</type>.
122
+
Support for <type>void</type> has been added.
105
123
</entry>
106
-
<entry>PHP 7.2.0</entry>
107
124
</row>
108
125
<row>
109
-
<entry><type>mixed</type></entry>
126
+
<entry>7.1.0</entry>
110
127
<entry>
111
-
The value can be any value.
128
+
Support for nullable types has been added.
112
129
</entry>
113
-
<entry>PHP 8.0.0</entry>
114
130
</row>
115
131
</tbody>
116
132
</tgroup>
117
133
</informaltable>
134
+
</sect2>
118
135

119
-
<warning>
120
-
<para>
121
-
Aliases for the above scalar types are not supported.
122
-
Instead, they are treated as class or interface names.
123
-
For example, using <literal>boolean</literal> as a type declaration
124
-
it will require the value to be an &instanceof; the class or
125
-
interface <literal>boolean</literal>, rather than of type
126
-
<type>bool</type>:
127
-
</para>
128
-
<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>
129
155
<example>
130
156
<programlisting role="php">
131
157
<![CDATA[
...
...
@@ -148,16 +174,296 @@ Stack trace:
148
174
]]>
149
175
</screen>
150
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.
151
206
</para>
152
-
</warning>
153
207

154
-
<sect3 xml:id="language.types.declarations.examples">
155
-
&reftitle.examples;
208
+
<note>
209
+
<simpara>
210
+
It is not possible to specify the signature of the function.
211
+
</simpara>
212
+
</note>
213
+
</sect3>
214
+

215
+
<sect3 xml:id="language.types.declarations.references">
216
+
<title>Type declarations on pass-by-reference Parameters</title>
217
+

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>
156
224
<example>
157
-
<title>Basic class type declaration</title>
225
+
<title>Typed pass-by-reference Parameters</title>
158
226
<programlisting role="php">
159
227
<![CDATA[
160
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
161
467
class C {}
162
468
class D extends C {}
163
469

...
...
@@ -173,9 +479,9 @@ f(new D);
173
479
f(new E);
174
480
?>
175
481
]]>
176
-
</programlisting>
177
-
&example.outputs.8;
178
-
<screen>
482
+
</programlisting>
483
+
&example.outputs.8;
484
+
<screen>
179
485
<![CDATA[
180
486
C
181
487
D
...
...
@@ -186,12 +492,12 @@ Stack trace:
186
492
#1 {main}
187
493
thrown in - on line 8
188
494
]]>
189
-
</screen>
190
-
</example>
495
+
</screen>
496
+
</example>
191
497

192
-
<example>
193
-
<title>Basic interface type declaration</title>
194
-
<programlisting role="php">
498
+
<example>
499
+
<title>Basic interface type declaration</title>
500
+
<programlisting role="php">
195
501
<![CDATA[
196
502
<?php
197
503
interface I { public function f(); }
...
...
@@ -208,9 +514,9 @@ f(new C);
208
514
f(new E);
209
515
?>
210
516
]]>
211
-
</programlisting>
212
-
&example.outputs.8;
213
-
<screen>
517
+
</programlisting>
518
+
&example.outputs.8;
519
+
<screen>
214
520
<![CDATA[
215
521
C
216
522

...
...
@@ -220,12 +526,12 @@ Stack trace:
220
526
#1 {main}
221
527
thrown in - on line 8
222
528
]]>
223
-
</screen>
224
-
</example>
529
+
</screen>
530
+
</example>
225
531

226
-
<example>
227
-
<title>Basic return type declaration</title>
228
-
<programlisting role="php">
532
+
<example>
533
+
<title>Basic return type declaration</title>
534
+
<programlisting role="php">
229
535
<![CDATA[
230
536
<?php
231
537
function sum($a, $b): float {
...
...
@@ -236,18 +542,18 @@ function sum($a, $b): float {
236
542
var_dump(sum(1, 2));
237
543
?>
238
544
]]>
239
-
</programlisting>
240
-
&example.outputs;
241
-
<screen>
545
+
</programlisting>
546
+
&example.outputs;
547
+
<screen>
242
548
<![CDATA[
243
549
float(3)
244
550
]]>
245
-
</screen>
246
-
</example>
551
+
</screen>
552
+
</example>
247
553

248
-
<example>
249
-
<title>Returning an object</title>
250
-
<programlisting role="php">
554
+
<example>
555
+
<title>Returning an object</title>
556
+
<programlisting role="php">
251
557
<![CDATA[
252
558
<?php
253
559
class C {}
...
...
@@ -259,32 +565,20 @@ function getC(): C {
259
565
var_dump(getC());
260
566
?>
261
567
]]>
262
-
</programlisting>
263
-
&example.outputs;
264
-
<screen>
568
+
</programlisting>
569
+
&example.outputs;
570
+
<screen>
265
571
<![CDATA[
266
572
object(C)#1 (0) {
267
573
}
268
574
]]>
269
-
</screen>
270
-
</example>
271
-
</sect3>
272
-
</sect2>
273
-

274
-
<sect2 xml:id="language.types.declarations.nullable">
275
-
<title>Nullable type</title>
276
-

277
-
<para>
278
-
As of PHP 7.1.0, type declarations can be marked nullable by prefixing the
279
-
type name with a question mark (<literal>?</literal>).
280
-
This signifies that the value can be of the specified type or &null;.
281
-
</para>
575
+
</screen>
576
+
</example>
282
577

283
-
<para>
284
-
<example>
285
-
<title>Nullable argument type declaration</title>
286
-
<programlisting role="php">
287
-
<![CDATA[
578
+
<example>
579
+
<title>Nullable argument type declaration</title>
580
+
<programlisting role="php">
581
+
<![CDATA[
288
582
<?php
289
583
class C {}
290
584

...
...
@@ -296,21 +590,21 @@ f(new C);
296
590
f(null);
297
591
?>
298
592
]]>
299
-
</programlisting>
300
-
&example.outputs;
301
-
<screen>
302
-
<![CDATA[
593
+
</programlisting>
594
+
&example.outputs;
595
+
<screen>
596
+
<![CDATA[
303
597
object(C)#1 (0) {
304
598
}
305
599
NULL
306
600
]]>
307
-
</screen>
308
-
</example>
601
+
</screen>
602
+
</example>
309
603

310
-
<example>
311
-
<title>Nullable return type declaration</title>
312
-
<programlisting role="php">
313
-
<![CDATA[
604
+
<example>
605
+
<title>Nullable return type declaration</title>
606
+
<programlisting role="php">
607
+
<![CDATA[
314
608
<?php
315
609
function get_item(): ?string {
316
610
if (isset($_GET['item'])) {
...
...
@@ -321,187 +615,32 @@ function get_item(): ?string {
321
615
}
322
616
?>
323
617
]]>
324
-
</programlisting>
325
-
</example>
326
-
</para>
618
+
</programlisting>
619
+
</example>
327
620

328
-
<note>
329
-
<para>
330
-
Prior to PHP 7.1.0, it was possible to achieve nullable arguments by making
331
-
<literal>null</literal> the default value.
332
-
This is not recommended as this breaks during inheritance.
333
-
</para>
334
-
<example>
335
-
<title>Old way to make arguments nullable</title>
336
-
<programlisting role="php">
621
+
<example>
622
+
<title>Class property type declaration</title>
623
+
<programlisting role="php">
337
624
<![CDATA[
338
625
<?php
339
-
class C {}
626
+
class User {
627
+
public static string $foo = 'foo';
340
628

341
-
function f(C $c = null) {
342
-
var_dump($c);
343
-
}
629
+
public int $id;
630
+
public string $username;
344
631

345
-
f(new C);
346
-
f(null);
347
-
?>
348
-
]]>
349
-
</programlisting>
350
-
&example.outputs;
351
-
<screen>
352
-
<![CDATA[
353
-
object(C)#1 (0) {
632
+
public function __construct(int $id, string $username) {
633
+
$this->id = $id;
634
+
$this->username = $username;
635
+
}
354
636
}
355
-
NULL
356
-
]]>
357
-
</screen>
358
-
</example>
359
-
</note>
360
-
</sect2>
361
-

362
-
<sect2 xml:id="language.types.declarations.union">
363
-
<title>Union types</title>
364
-
<para>
365
-
A union type declaration accepts values of multiple different types,
366
-
rather than a single one.
367
-
Union types are specified using the syntax <literal>T1|T2|...</literal>.
368
-
Union types are available as of PHP 8.0.0.
369
-
</para>
370
-

371
-
<sect3 xml:id="language.types.declarations.union.nullable">
372
-
<title>Nullable union types</title>
373
-
<para>
374
-
The <literal>null</literal> type is supported as part of unions,
375
-
such that <literal>T1|T2|null</literal> can be used to create a nullable union.
376
-
The existing <literal>?T</literal> notation is considered a shorthand
377
-
for the common case of <literal>T|null</literal>.
378
-
</para>
379
-

380
-
<caution>
381
-
<simpara>
382
-
<literal>null</literal> cannot be used as a standalone type.
383
-
</simpara>
384
-
</caution>
385
-
</sect3>
386
-

387
-
<sect3 xml:id="language.types.declarations.union.false">
388
-
<title>false pseudo-type</title>
389
-
<para>
390
-
The <literal>false</literal> literal type is supported as part of unions,
391
-
and is included as for historical reasons many internal functions return
392
-
<literal>false</literal> instead of <literal>null</literal> for failures.
393
-
A classic example of such a function is <function>strpos</function>.
394
-
</para>
395
-

396
-
<caution>
397
-
<simpara>
398
-
<literal>false</literal> cannot be used as a standalone type (including
399
-
nullable standalone type).
400
-
As such, all of <literal>false</literal>, <literal>false|null</literal>
401
-
and <literal>?false</literal> are not permitted.
402
-
</simpara>
403
-
</caution>
404
-
<caution>
405
-
<simpara>
406
-
The <literal>true</literal> literal type does <emphasis>not</emphasis>
407
-
exist.
408
-
</simpara>
409
-
</caution>
410
-
</sect3>
411
-

412
-
<sect3 xml:id="language.types.declarations.union.redundant">
413
-
<title>Duplicate and redundant types</title>
414
-
<para>
415
-
To catch simple bugs in union type declarations, redundant types that
416
-
can be detected without performing class loading will result in a
417
-
compile-time error. This includes:
418
-

419
-
<itemizedlist>
420
-
<listitem>
421
-
<simpara>
422
-
Each name-resolved type may only occur once. Types such as
423
-
<literal>int|string|INT</literal> result in an error.
424
-
</simpara>
425
-
</listitem>
426
-
<listitem>
427
-
<simpara>
428
-
If <type>bool</type> is used, <type>false</type> cannot be used additionally.
429
-
</simpara>
430
-
</listitem>
431
-
<listitem>
432
-
<simpara>
433
-
If <type>object</type> is used, class types cannot be used additionally.
434
-
</simpara>
435
-
</listitem>
436
-
<listitem>
437
-
<simpara>
438
-
If <type>iterable</type> is used, <type>array</type>
439
-
and <classname>Traversable</classname> cannot be used additionally.
440
-
</simpara>
441
-
</listitem>
442
-
</itemizedlist>
443
-
</para>
444
-

445
-
<note>
446
-
<simpara>
447
-
This does not guarantee that the type is “minimal”, because doing so would
448
-
require loading all used class types.
449
-
</simpara>
450
-
</note>
451
-

452
-
<para>
453
-
For example, if <literal>A</literal> and <literal>B</literal> are class
454
-
aliases, then <literal>A|B</literal> remains a legal union type, even
455
-
though it could be reduced to either <literal>A</literal> or
456
-
<literal>B</literal>.
457
-
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
458
-
is also a legal union type, even though it could be reduced to just
459
-
<literal>A</literal>.
460
-

461
-
<informalexample>
462
-
<programlisting role="php">
463
-
<![CDATA[
464
-
<?php
465
-
function foo(): int|INT {} // Disallowed
466
-
function foo(): bool|false {} // Disallowed
467
-

468
-
use A as B;
469
-
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
470
-

471
-
class_alias('X', 'Y');
472
-
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
473
637
?>
474
638
]]>
475
-
</programlisting>
476
-
</informalexample>
477
-
</para>
478
-
</sect3>
479
-

480
-
</sect2>
481
-

482
-
<sect2 xml:id="language.types.declarations.return-only">
483
-
<title>Return only types</title>
484
-

485
-
<sect3 xml:id="language.types.declarations.void">
486
-
<title>void</title>
487
-
<para>
488
-
<literal>void</literal> is a return type indicating the function does not
489
-
return a value.
490
-
Therefore it cannot be part of a union type declaration.
491
-
Available as of PHP 7.1.0.
492
-
</para>
493
-
</sect3>
494
-

495
-
<sect3 xml:id="language.types.declarations.static">
496
-
<title>static</title>
497
-
<para>
498
-
The value must be an &instanceof; the same class as the one the
499
-
method is called in.
500
-
Available as of PHP 8.0.0.
501
-
</para>
502
-
</sect3>
639
+
</programlisting>
640
+
</example>
503
641
</sect2>
504
642

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

...
...
@@ -635,161 +774,7 @@ Stack trace:
635
774
</example>
636
775
</sect2>
637
776

638
-
<sect2 xml:id="language.types.declarations.union.coercive">
639
-
<title>Coercive typing with union types</title>
640
-
<para>
641
-
When <literal>strict_types</literal> is not enabled, scalar type declarations
642
-
are subject to limited implicit type coercions.
643
-
If the exact type of the value is not part of the union, then the target type
644
-
is chosen in the following order of preference:
645
-

646
-
<orderedlist>
647
-
<listitem>
648
-
<simpara>
649
-
<type>int</type>
650
-
</simpara>
651
-
</listitem>
652
-
<listitem>
653
-
<simpara>
654
-
<type>float</type>
655
-
</simpara>
656
-
</listitem>
657
-
<listitem>
658
-
<simpara>
659
-
<type>string</type>
660
-
</simpara>
661
-
</listitem>
662
-
<listitem>
663
-
<simpara>
664
-
<type>bool</type>
665
-
</simpara>
666
-
</listitem>
667
-
</orderedlist>
668
-

669
-
If the type both exists in the union, and the value can be coerced to the
670
-
type under PHPs existing type checking semantics, then the type is chosen.
671
-
Otherwise the next type is tried.
672
-
</para>
673
-

674
-
<caution>
675
-
<para>
676
-
As an exception, if the value is a string and both int and float are part
677
-
of the union, the preferred type is determined by the existing
678
-
“numeric string” semantics.
679
-
For example, for <literal>"42"</literal> <type>int</type> is chosen,
680
-
while for <literal>"42.0"</literal> <type>float</type> is chosen.
681
-
</para>
682
-
</caution>
683
-

684
-
<note>
685
-
<para>
686
-
Types that are not part of the above preference list are not eligible
687
-
targets for implicit coercion. In particular no implicit coercions to
688
-
the <literal>null</literal> and <literal>false</literal> types occur.
689
-
</para>
690
-
</note>
691
-

692
-
<example>
693
-
<title>Example of types being coerced into a type part of the union</title>
694
-
<programlisting role="php">
695
-
<![CDATA[
696
-
<?php
697
-
// int|string
698
-
42 --> 42 // exact type
699
-
"42" --> "42" // exact type
700
-
new ObjectWithToString --> "Result of __toString()"
701
-
// object never compatible with int, fall back to string
702
-
42.0 --> 42 // float compatible with int
703
-
42.1 --> 42 // float compatible with int
704
-
1e100 --> "1.0E+100" // float too large for int type, fall back to string
705
-
INF --> "INF" // float too large for int type, fall back to string
706
-
true --> 1 // bool compatible with int
707
-
[] --> TypeError // array not compatible with int or string
708
-

709
-
// int|float|bool
710
-
"45" --> 45 // int numeric string
711
-
"45.0" --> 45.0 // float numeric string
712
-

713
-
"45X" --> true // not numeric string, fall back to bool
714
-
"" --> false // not numeric string, fall back to bool
715
-
"X" --> true // not numeric string, fall back to bool
716
-
[] --> TypeError // array not compatible with int, float or bool
717
-
?>
718
-
]]>
719
-
</programlisting>
720
-
</example>
721
-
</sect2>
722
-

723
-
<!-- TODO figure out what do to with these things -->
724
-
<sect2 xml:id="language.types.declarations.misc">
725
-
<title>Misc</title>
726
-
<example>
727
-
<title>Typed pass-by-reference Parameters</title>
728
-
<simpara>
729
-
Declared types of reference parameters are checked on function entry, but
730
-
not when the function returns, so after the function had returned, the
731
-
argument's type may have changed.
732
-
</simpara>
733
-
<programlisting role="php">
734
-
<![CDATA[
735
-
<?php
736
-
function array_baz(array &$param)
737
-
{
738
-
$param = 1;
739
-
}
740
-
$var = [];
741
-
array_baz($var);
742
-
var_dump($var);
743
-
array_baz($var);
744
-
?>
745
-
]]>
746
-
</programlisting>
747
-
&example.outputs.8;
748
-
<screen>
749
-
<![CDATA[
750
-
int(1)
751
-

752
-
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
753
-
Stack trace:
754
-
#0 -(9): array_baz(1)
755
-
#1 {main}
756
-
thrown in - on line 2
757
-
]]>
758
-
</screen>
759
-
</example>
760
-

761
-
<example>
762
-
<title>Catching <classname>TypeError</classname></title>
763
-
<programlisting role="php">
764
-
<![CDATA[
765
-
<?php
766
-
declare(strict_types=1);
767
-

768
-
function sum(int $a, int $b) {
769
-
return $a + $b;
770
-
}
771
-

772
-
try {
773
-
var_dump(sum(1, 2));
774
-
var_dump(sum(1.5, 2.5));
775
-
} catch (TypeError $e) {
776
-
echo 'Error: ', $e->getMessage();
777
-
}
778
-
?>
779
-
]]>
780
-
</programlisting>
781
-
&example.outputs.8;
782
-
<screen>
783
-
<![CDATA[
784
-
int(3)
785
-
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
786
-
]]>
787
-
</screen>
788
-
</example>
789
-
</sect2>
790
-

791
777
</sect1>
792
-

793
778
<!-- Keep this comment at the end of the file
794
779
Local variables:
795
780
mode: sgml
796
781