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>
37
55
<entry>
38
-
The value must be an &instanceof; the given class or interface.
56
+
Support for the literal type <type>true</type> has been added.
39
57
</entry>
40
-
<entry/>
41
58
</row>
42
59
<row>
43
-
<entry><type>self</type></entry>
60
+
<entry>8.2.0</entry>
44
61
<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.
62
+
The types <type>null</type> and <type>false</type> can now be used standalone.
48
63
</entry>
49
-
<entry/>
50
64
</row>
51
65
<row>
52
-
<entry><type>parent</type></entry>
66
+
<entry>8.1.0</entry>
53
67
<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.
68
+
Support for intersection types has been added.
57
69
</entry>
58
-
<entry/>
59
70
</row>
60
71
<row>
61
-
<entry><type>array</type></entry>
72
+
<entry>8.1.0</entry>
62
73
<entry>
63
-
The value must be an <type>array</type>.
74
+
Returning by reference from a <type>void</type> function is now deprecated.
64
75
</entry>
65
-
<entry/>
66
76
</row>
67
77
<row>
68
-
<entry><type>callable</type></entry>
78
+
<entry>8.1.0</entry>
69
79
<entry>
70
-
The value must be a valid <type>callable</type>.
71
-
Cannot be used as a class property type declaration.
80
+
Support for the return only type <type>never</type> has been added.
72
81
</entry>
73
-
<entry/>
74
82
</row>
75
83
<row>
76
-
<entry><type>bool</type></entry>
84
+
<entry>8.0.0</entry>
77
85
<entry>
78
-
The value must be a boolean value.
86
+
Support for <type>mixed</type> has been added.
79
87
</entry>
80
-
<entry/>
81
88
</row>
82
89
<row>
83
-
<entry><type>float</type></entry>
90
+
<entry>8.0.0</entry>
84
91
<entry>
85
-
The value must be a floating point number.
92
+
Support for the return only type <type>static</type> has been added.
86
93
</entry>
87
-
<entry/>
88
94
</row>
89
95
<row>
90
-
<entry><type>int</type></entry>
96
+
<entry>8.0.0</entry>
91
97
<entry>
92
-
The value must be an integer.
98
+
Support for union types has been added.
93
99
</entry>
94
-
<entry/>
95
100
</row>
96
101
<row>
97
-
<entry><type>string</type></entry>
102
+
<entry>7.4.0</entry>
98
103
<entry>
99
-
The value must be a <type>string</type>.
104
+
Support for class properties typing has been added.
100
105
</entry>
101
-
<entry/>
102
106
</row>
103
107
<row>
104
-
<entry><type>iterable</type></entry>
108
+
<entry>7.2.0</entry>
105
109
<entry>
106
-
The value must be either an <type>array</type> or an &instanceof; <classname>Traversable</classname>.
110
+
Support for <type>object</type> has been added.
107
111
</entry>
108
-
<entry>PHP 7.1.0</entry>
109
112
</row>
110
113
<row>
111
-
<entry><type>object</type></entry>
114
+
<entry>7.1.0</entry>
112
115
<entry>
113
-
The value must be an <type>object</type>.
116
+
Support for <type>iterable</type> has been added.
114
117
</entry>
115
-
<entry>PHP 7.2.0</entry>
116
118
</row>
117
119
<row>
118
-
<entry><type>mixed</type></entry>
120
+
<entry>7.1.0</entry>
119
121
<entry>
120
-
The value can be any value.
122
+
Support for <type>void</type> has been added.
123
+
</entry>
124
+
</row>
125
+
<row>
126
+
<entry>7.1.0</entry>
127
+
<entry>
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,205 +174,146 @@ Stack trace:
156
174
]]>
157
175
</screen>
158
176
</example>
159
-
</para>
160
-
</warning>
161
-

162
-
<sect3 xml:id="language.types.declarations.mixed">
163
-
<title>mixed</title>
164
-

165
-
<para>
166
-
<type>mixed</type> is equivalent to the <link linkend="language.types.declarations.composite.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>
177
+
</warning>
178
+
</sect3>
174
179

175
-
<sect3 xml:id="language.types.declarations.examples">
176
-
&reftitle.examples;
177
-
<example>
178
-
<title>Basic class type declaration</title>
179
-
<programlisting role="php">
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">
180
191
<![CDATA[
181
192
<?php
182
-
class C {}
183
-
class D extends C {}
184
-

185
-
// This doesn't extend C.
186
-
class E {}
187
-

188
-
function f(C $c) {
189
-
echo get_class($c)."\n";
190
-
}
191
-

192
-
f(new C);
193
-
f(new D);
194
-
f(new E);
193
+
function &test(): void {}
195
194
?>
196
195
]]>
197
-
</programlisting>
198
-
&example.outputs.8;
199
-
<screen>
200
-
<![CDATA[
201
-
C
202
-
D
203
-

204
-
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
205
-
Stack trace:
206
-
#0 -(14): f(Object(E))
207
-
#1 {main}
208
-
thrown in - on line 8
209
-
]]>
210
-
</screen>
211
-
</example>
212
-

213
-
<example>
214
-
<title>Basic interface type declaration</title>
215
-
<programlisting role="php">
216
-
<![CDATA[
217
-
<?php
218
-
interface I { public function f(); }
219
-
class C implements I { public function f() {} }
220
-

221
-
// This doesn't implement I.
222
-
class E {}
196
+
</programlisting>
197
+
</informalexample>
198
+
</para>
199
+
</note>
200
+
</sect3>
223
201

224
-
function f(I $i) {
225
-
echo get_class($i)."\n";
226
-
}
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.
206
+
</para>
227
207

228
-
f(new C);
229
-
f(new E);
230
-
?>
231
-
]]>
232
-
</programlisting>
233
-
&example.outputs.8;
234
-
<screen>
235
-
<![CDATA[
236
-
C
208
+
<note>
209
+
<simpara>
210
+
It is not possible to specify the signature of the function.
211
+
</simpara>
212
+
</note>
213
+
</sect3>
237
214

238
-
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
239
-
Stack trace:
240
-
#0 -(13): f(Object(E))
241
-
#1 {main}
242
-
thrown in - on line 8
243
-
]]>
244
-
</screen>
245
-
</example>
215
+
<sect3 xml:id="language.types.declarations.references">
216
+
<title>Type declarations on pass-by-reference Parameters</title>
246
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>
247
224
<example>
248
-
<title>Basic return type declaration</title>
225
+
<title>Typed pass-by-reference Parameters</title>
249
226
<programlisting role="php">
250
227
<![CDATA[
251
228
<?php
252
-
function sum($a, $b): float {
253
-
return $a + $b;
229
+
function array_baz(array &$param)
230
+
{
231
+
$param = 1;
254
232
}
255
-

256
-
// Note that a float will be returned.
257
-
var_dump(sum(1, 2));
233
+
$var = [];
234
+
array_baz($var);
235
+
var_dump($var);
236
+
array_baz($var);
258
237
?>
259
238
]]>
260
239
</programlisting>
261
-
&example.outputs;
240
+
&example.outputs.similar;
262
241
<screen>
263
242
<![CDATA[
264
-
float(3)
265
-
]]>
266
-
</screen>
267
-
</example>
268
-

269
-
<example>
270
-
<title>Returning an object</title>
271
-
<programlisting role="php">
272
-
<![CDATA[
273
-
<?php
274
-
class C {}
275
-

276
-
function getC(): C {
277
-
return new C;
278
-
}
243
+
int(1)
279
244

280
-
var_dump(getC());
281
-
?>
282
-
]]>
283
-
</programlisting>
284
-
&example.outputs;
285
-
<screen>
286
-
<![CDATA[
287
-
object(C)#1 (0) {
288
-
}
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
289
250
]]>
290
251
</screen>
291
252
</example>
292
253
</sect3>
293
254
</sect2>
294
255

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

256
+
<sect2 xml:id="language.types.declarations.composite">
257
+
<title>Composite Types Usage Notes</title>
298
258
<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;.
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.
302
261
</para>
303
262

304
-
<para>
305
-
<example>
306
-
<title>Nullable argument type declaration</title>
307
-
<programlisting role="php">
308
-
<![CDATA[
309
-
<?php
310
-
class C {}
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>
311
269

312
-
function f(?C $c) {
313
-
var_dump($c);
314
-
}
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>
315
279

316
-
f(new C);
317
-
f(null);
318
-
?>
319
-
]]>
320
-
</programlisting>
321
-
&example.outputs;
322
-
<screen>
323
-
<![CDATA[
324
-
object(C)#1 (0) {
325
-
}
326
-
NULL
327
-
]]>
328
-
</screen>
329
-
</example>
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>
330
289

331
-
<example>
332
-
<title>Nullable return type declaration</title>
333
-
<programlisting role="php">
334
-
<![CDATA[
335
-
<?php
336
-
function get_item(): ?string {
337
-
if (isset($_GET['item'])) {
338
-
return $_GET['item'];
339
-
} else {
340
-
return null;
341
-
}
342
-
}
343
-
?>
344
-
]]>
345
-
</programlisting>
346
-
</example>
347
-
</para>
290
+
<sect4 xml:id="language.types.declarations.nullable">
291
+
<title>Nullable type syntactic sugar</title>
348
292

349
-
<note>
350
-
<para>
351
-
It is 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">
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">
358
317
<![CDATA[
359
318
<?php
360
319
class C {}
...
...
@@ -367,106 +326,20 @@ f(new C);
367
326
f(null);
368
327
?>
369
328
]]>
370
-
</programlisting>
371
-
&example.outputs;
372
-
<screen>
329
+
</programlisting>
330
+
&example.outputs;
331
+
<screen>
373
332
<![CDATA[
374
333
object(C)#1 (0) {
375
334
}
376
335
NULL
377
336
]]>
378
-
</screen>
379
-
</example>
380
-
</note>
381
-
</sect2>
382
-

383
-
<sect2 xml:id="language.types.declarations.composite">
384
-
<title>Composite types</title>
385
-
<para>
386
-
It is possible to combine simple types into composite types.
387
-
PHP allows types to be combined in the following ways:
388
-
</para>
389
-

390
-
<itemizedlist>
391
-
<listitem>
392
-
<simpara>
393
-
Union of simple types. As of PHP 8.0.0.
394
-
</simpara>
395
-
</listitem>
396
-
<listitem>
397
-
<simpara>
398
-
Intersection of class-types (interfaces and class names). As of PHP 8.1.0.
399
-
</simpara>
400
-
</listitem>
401
-
</itemizedlist>
402
-

403
-
<caution>
404
-
<simpara>
405
-
It is not possible to combine intersection types with union types.
406
-
</simpara>
407
-
</caution>
408
-

409
-
<sect3 xml:id="language.types.declarations.composite.union">
410
-
<title>Union types</title>
411
-
<para>
412
-
A union type declaration accepts values of multiple different simple types,
413
-
rather than a single one.
414
-
Union types are specified using the syntax <literal>T1|T2|...</literal>.
415
-
Union types are available as of PHP 8.0.0.
416
-
</para>
417
-

418
-
<sect4 xml:id="language.types.declarations.composite.union.nullable">
419
-
<title>Nullable union types</title>
420
-
<para>
421
-
The <literal>null</literal> type is supported as part of unions,
422
-
such that <literal>T1|T2|null</literal> can be used to create a nullable union.
423
-
The existing <literal>?T</literal> notation is considered a shorthand
424
-
for the common case of <literal>T|null</literal>.
425
-
</para>
426
-

427
-
<caution>
428
-
<simpara>
429
-
<literal>null</literal> cannot be used as a standalone type.
430
-
</simpara>
431
-
</caution>
432
-
</sect4>
433
-

434
-
<sect4 xml:id="language.types.declarations.composite.union.false">
435
-
<title>false pseudo-type</title>
436
-
<para>
437
-
The <literal>false</literal> literal type is supported as part of unions,
438
-
and is included as for historical reasons many internal functions return
439
-
<literal>false</literal> instead of <literal>null</literal> for failures.
440
-
A classic example of such a function is <function>strpos</function>.
441
-
</para>
442
-

443
-
<caution>
444
-
<simpara>
445
-
<literal>false</literal> cannot be used as a standalone type (including
446
-
nullable standalone type).
447
-
As such, <literal>false</literal>, <literal>false|null</literal>
448
-
and <literal>?false</literal> are not permitted.
449
-
</simpara>
450
-
</caution>
451
-
<caution>
452
-
<simpara>
453
-
The <literal>true</literal> literal type does <emphasis>not</emphasis>
454
-
exist.
455
-
</simpara>
456
-
</caution>
337
+
</screen>
338
+
</example>
339
+
</note>
457
340
</sect4>
458
341
</sect3>
459
342

460
-
<sect3 xml:id="language.types.declarations.composite.intersection">
461
-
<title>Intersection types</title>
462
-
<para>
463
-
An intersection type declaration accepts values which satisfies multiple
464
-
class-type declarations, rather than a single one.
465
-
Intersection types are specified using the syntax <literal>T1&amp;T2&amp;...</literal>.
466
-
Intersection types are available as of PHP 8.1.0.
467
-
</para>
468
-
</sect3>
469
-

470
343
<sect3 xml:id="language.types.declarations.composite.redundant">
471
344
<title>Duplicate and redundant types</title>
472
345
<para>
...
...
@@ -493,7 +366,8 @@ NULL
493
366
<itemizedlist>
494
367
<listitem>
495
368
<simpara>
496
-
If <type>bool</type> is used, <type>false</type> cannot be used additionally.
369
+
If <type>bool</type> is used, <type>false</type> or <type>true</type>
370
+
cannot be used additionally.
497
371
</simpara>
498
372
</listitem>
499
373
<listitem>
...
...
@@ -525,107 +399,248 @@ NULL
525
399
</listitem>
526
400
</itemizedlist>
527
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>
528
417
</itemizedlist>
529
418
</para>
530
419

531
-
<note>
532
-
<simpara>
533
-
This does not guarantee that the type is “minimal”, because doing so would
534
-
require loading all used class types.
535
-
</simpara>
536
-
</note>
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
467
+
class C {}
468
+
class D extends C {}
469
+

470
+
// This doesn't extend C.
471
+
class E {}
472
+

473
+
function f(C $c) {
474
+
echo get_class($c)."\n";
475
+
}
476
+

477
+
f(new C);
478
+
f(new D);
479
+
f(new E);
480
+
?>
481
+
]]>
482
+
</programlisting>
483
+
&example.outputs.8;
484
+
<screen>
485
+
<![CDATA[
486
+
C
487
+
D
488
+

489
+
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
490
+
Stack trace:
491
+
#0 -(14): f(Object(E))
492
+
#1 {main}
493
+
thrown in - on line 8
494
+
]]>
495
+
</screen>
496
+
</example>
497
+

498
+
<example>
499
+
<title>Basic interface type declaration</title>
500
+
<programlisting role="php">
501
+
<![CDATA[
502
+
<?php
503
+
interface I { public function f(); }
504
+
class C implements I { public function f() {} }
537
505

538
-
<para>
539
-
For example, if <literal>A</literal> and <literal>B</literal> are class
540
-
aliases, then <literal>A|B</literal> remains a legal union type, even
541
-
though it could be reduced to either <literal>A</literal> or
542
-
<literal>B</literal>.
543
-
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
544
-
is also a legal union type, even though it could be reduced to just
545
-
<literal>A</literal>.
506
+
// This doesn't implement I.
507
+
class E {}
546
508

547
-
<informalexample>
548
-
<programlisting role="php">
509
+
function f(I $i) {
510
+
echo get_class($i)."\n";
511
+
}
512
+

513
+
f(new C);
514
+
f(new E);
515
+
?>
516
+
]]>
517
+
</programlisting>
518
+
&example.outputs.8;
519
+
<screen>
549
520
<![CDATA[
550
-
<?php
551
-
function foo(): int|INT {} // Disallowed
552
-
function foo(): bool|false {} // Disallowed
553
-
function foo(): int&Traversable {} // Disallowed
554
-
function foo(): self&Traversable {} // Disallowed
521
+
C
555
522

556
-
use A as B;
557
-
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
558
-
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
523
+
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
524
+
Stack trace:
525
+
#0 -(13): f(Object(E))
526
+
#1 {main}
527
+
thrown in - on line 8
528
+
]]>
529
+
</screen>
530
+
</example>
559
531

560
-
class_alias('X', 'Y');
561
-
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
562
-
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
532
+
<example>
533
+
<title>Basic return type declaration</title>
534
+
<programlisting role="php">
535
+
<![CDATA[
536
+
<?php
537
+
function sum($a, $b): float {
538
+
return $a + $b;
539
+
}
540
+

541
+
// Note that a float will be returned.
542
+
var_dump(sum(1, 2));
563
543
?>
564
544
]]>
565
-
</programlisting>
566
-
</informalexample>
567
-
</para>
568
-
</sect3>
569
-
</sect2>
545
+
</programlisting>
546
+
&example.outputs;
547
+
<screen>
548
+
<![CDATA[
549
+
float(3)
550
+
]]>
551
+
</screen>
552
+
</example>
570
553

571
-
<sect2 xml:id="language.types.declarations.return-only">
572
-
<title>Return only types</title>
554
+
<example>
555
+
<title>Returning an object</title>
556
+
<programlisting role="php">
557
+
<![CDATA[
558
+
<?php
559
+
class C {}
573
560

574
-
<sect3 xml:id="language.types.declarations.void">
575
-
<title>void</title>
576
-
<para>
577
-
<literal>void</literal> is a return type indicating the function does not
578
-
return a value.
579
-
Therefore it cannot be part of a union type declaration.
580
-
Available as of PHP 7.1.0.
581
-
</para>
582
-
<note>
583
-
<para>
584
-
Returning by reference from a <type>void</type> function is deprecated as of PHP 8.1.0,
585
-
because such a function is contradictory.
586
-
Previously, it already emitted the following
587
-
<constant>E_NOTICE</constant> when called:
588
-
<literal>Only variable references should be returned by reference</literal>.
561
+
function getC(): C {
562
+
return new C;
563
+
}
589
564

590
-
<informalexample>
591
-
<programlisting role="php">
565
+
var_dump(getC());
566
+
?>
567
+
]]>
568
+
</programlisting>
569
+
&example.outputs;
570
+
<screen>
592
571
<![CDATA[
572
+
object(C)#1 (0) {
573
+
}
574
+
]]>
575
+
</screen>
576
+
</example>
577
+

578
+
<example>
579
+
<title>Nullable argument type declaration</title>
580
+
<programlisting role="php">
581
+
<![CDATA[
593
582
<?php
594
-
function &test(): void {}
583
+
class C {}
584
+

585
+
function f(?C $c) {
586
+
var_dump($c);
587
+
}
588
+

589
+
f(new C);
590
+
f(null);
595
591
?>
596
592
]]>
597
-
</programlisting>
598
-
</informalexample>
599
-
</para>
600
-
</note>
601
-
</sect3>
593
+
</programlisting>
594
+
&example.outputs;
595
+
<screen>
596
+
<![CDATA[
597
+
object(C)#1 (0) {
598
+
}
599
+
NULL
600
+
]]>
601
+
</screen>
602
+
</example>
602
603

603
-
<sect3 xml:id="language.types.declarations.never">
604
-
<title>never</title>
605
-
<para>
606
-
<literal>never</literal> is a return type indicating the function does not
607
-
return. This means that it either calls <function>exit</function>, throws
608
-
an exception, or is an infinite loop.
609
-
Therefore it cannot be part of a union type declaration.
610
-
Available as of PHP 8.1.0.
611
-
</para>
612
-
<para>
613
-
<type>never</type> is, in type theory parlance, the bottom type.
614
-
Meaning it is the subtype of every other type and can replace any other
615
-
return type during inheritance.
616
-
</para>
617
-
</sect3>
604
+
<example>
605
+
<title>Nullable return type declaration</title>
606
+
<programlisting role="php">
607
+
<![CDATA[
608
+
<?php
609
+
function get_item(): ?string {
610
+
if (isset($_GET['item'])) {
611
+
return $_GET['item'];
612
+
} else {
613
+
return null;
614
+
}
615
+
}
616
+
?>
617
+
]]>
618
+
</programlisting>
619
+
</example>
618
620

619
-
<sect3 xml:id="language.types.declarations.static">
620
-
<title>static</title>
621
-
<para>
622
-
The value must be an &instanceof; the same class as the one the
623
-
method is called in.
624
-
Available as of PHP 8.0.0.
625
-
</para>
626
-
</sect3>
621
+
<example>
622
+
<title>Class property type declaration</title>
623
+
<programlisting role="php">
624
+
<![CDATA[
625
+
<?php
626
+
class User {
627
+
public static string $foo = 'foo';
628
+

629
+
public int $id;
630
+
public string $username;
631
+

632
+
public function __construct(int $id, string $username) {
633
+
$this->id = $id;
634
+
$this->username = $username;
635
+
}
636
+
}
637
+
?>
638
+
]]>
639
+
</programlisting>
640
+
</example>
627
641
</sect2>
628
642

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

...
...
@@ -759,161 +774,7 @@ Stack trace:
759
774
</example>
760
775
</sect2>
761
776

762
-
<sect2 xml:id="language.types.declarations.union.coercive">
763
-
<title>Coercive typing with union types</title>
764
-
<para>
765
-
When <literal>strict_types</literal> is not enabled, scalar type declarations
766
-
are subject to limited implicit type coercions.
767
-
If the exact type of the value is not part of the union, then the target type
768
-
is chosen in the following order of preference:
769
-

770
-
<orderedlist>
771
-
<listitem>
772
-
<simpara>
773
-
<type>int</type>
774
-
</simpara>
775
-
</listitem>
776
-
<listitem>
777
-
<simpara>
778
-
<type>float</type>
779
-
</simpara>
780
-
</listitem>
781
-
<listitem>
782
-
<simpara>
783
-
<type>string</type>
784
-
</simpara>
785
-
</listitem>
786
-
<listitem>
787
-
<simpara>
788
-
<type>bool</type>
789
-
</simpara>
790
-
</listitem>
791
-
</orderedlist>
792
-

793
-
If the type both exists in the union, and the value can be coerced to the
794
-
type under PHPs existing type checking semantics, then the type is chosen.
795
-
Otherwise the next type is tried.
796
-
</para>
797
-

798
-
<caution>
799
-
<para>
800
-
As an exception, if the value is a string and both int and float are part
801
-
of the union, the preferred type is determined by the existing
802
-
“numeric string” semantics.
803
-
For example, for <literal>"42"</literal> <type>int</type> is chosen,
804
-
while for <literal>"42.0"</literal> <type>float</type> is chosen.
805
-
</para>
806
-
</caution>
807
-

808
-
<note>
809
-
<para>
810
-
Types that are not part of the above preference list are not eligible
811
-
targets for implicit coercion. In particular no implicit coercions to
812
-
the <literal>null</literal> and <literal>false</literal> types occur.
813
-
</para>
814
-
</note>
815
-

816
-
<example>
817
-
<title>Example of types being coerced into a type part of the union</title>
818
-
<programlisting role="php">
819
-
<![CDATA[
820
-
<?php
821
-
// int|string
822
-
42 --> 42 // exact type
823
-
"42" --> "42" // exact type
824
-
new ObjectWithToString --> "Result of __toString()"
825
-
// object never compatible with int, fall back to string
826
-
42.0 --> 42 // float compatible with int
827
-
42.1 --> 42 // float compatible with int
828
-
1e100 --> "1.0E+100" // float too large for int type, fall back to string
829
-
INF --> "INF" // float too large for int type, fall back to string
830
-
true --> 1 // bool compatible with int
831
-
[] --> TypeError // array not compatible with int or string
832
-

833
-
// int|float|bool
834
-
"45" --> 45 // int numeric string
835
-
"45.0" --> 45.0 // float numeric string
836
-

837
-
"45X" --> true // not numeric string, fall back to bool
838
-
"" --> false // not numeric string, fall back to bool
839
-
"X" --> true // not numeric string, fall back to bool
840
-
[] --> TypeError // array not compatible with int, float or bool
841
-
?>
842
-
]]>
843
-
</programlisting>
844
-
</example>
845
-
</sect2>
846
-

847
-
<!-- TODO figure out what do to with these things -->
848
-
<sect2 xml:id="language.types.declarations.misc">
849
-
<title>Misc</title>
850
-
<example>
851
-
<title>Typed pass-by-reference Parameters</title>
852
-
<simpara>
853
-
Declared types of reference parameters are checked on function entry, but
854
-
not when the function returns, so after the function had returned, the
855
-
argument's type may have changed.
856
-
</simpara>
857
-
<programlisting role="php">
858
-
<![CDATA[
859
-
<?php
860
-
function array_baz(array &$param)
861
-
{
862
-
$param = 1;
863
-
}
864
-
$var = [];
865
-
array_baz($var);
866
-
var_dump($var);
867
-
array_baz($var);
868
-
?>
869
-
]]>
870
-
</programlisting>
871
-
&example.outputs.8;
872
-
<screen>
873
-
<![CDATA[
874
-
int(1)
875
-

876
-
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
877
-
Stack trace:
878
-
#0 -(9): array_baz(1)
879
-
#1 {main}
880
-
thrown in - on line 2
881
-
]]>
882
-
</screen>
883
-
</example>
884
-

885
-
<example>
886
-
<title>Catching <classname>TypeError</classname></title>
887
-
<programlisting role="php">
888
-
<![CDATA[
889
-
<?php
890
-
declare(strict_types=1);
891
-

892
-
function sum(int $a, int $b) {
893
-
return $a + $b;
894
-
}
895
-

896
-
try {
897
-
var_dump(sum(1, 2));
898
-
var_dump(sum(1.5, 2.5));
899
-
} catch (TypeError $e) {
900
-
echo 'Error: ', $e->getMessage();
901
-
}
902
-
?>
903
-
]]>
904
-
</programlisting>
905
-
&example.outputs.8;
906
-
<screen>
907
-
<![CDATA[
908
-
int(3)
909
-
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
910
-
]]>
911
-
</screen>
912
-
</example>
913
-
</sect2>
914
-

915
777
</sect1>
916
-

917
778
<!-- Keep this comment at the end of the file
918
779
Local variables:
919
780
mode: sgml
920
781