[prev in list] [next in list] [prev in thread] [next in thread]
List: php-doc-cvs
Subject: [DOC-CVS] [doc-en] master: Rewrite type section (#1726)
From: George Peter Banyard via GitHub <noreply () php ! net>
Date: 2022-11-30 15:50:48
Message-ID: 8V0YSdsfaGMerl7296zs9Apr4DOqy47pQBJp90neM () main ! php ! net
[Download RAW message or body]
Author: George Peter Banyard (Girgias)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2022-11-30T15:39:41Z
Commit: https://github.com/php/doc-en/commit/161dde4fe721309398dd324edbf02aec409f127b
Raw diff: https://github.com/php/doc-en/commit/161dde4fe721309398dd324edbf02aec409f127b.diff
Rewrite type section (#1726)
This commit rewrites the whole type section to (hopefully) be better structured and \
future proof for further additions to the type system.
* Each type now gets their individual page instead of being shoved in the type \
declaration page.
* A type system page is added which describes PHP's type system, regardless if it is \
possible to declare the type in userland or not. Therefore, the type declaration page \
only has information related to writing type declarations in userland.
* The description of strict_type and the type coercion is moved into the type \
juggling page.
* Remove outdated information in string implementation section
* Add paragraph about using non string in string context can throw
Co-authored-by: Christoph M. Becker <cmbecker69@gmx.de>
Changed paths:
A language/types/literal.xml
A language/types/mixed.xml
A language/types/never.xml
A language/types/relative-class-types.xml
A language/types/type-system.xml
A language/types/void.xml
M appendices/migration81/new-features.xml
M language/oop5/properties.xml
M language/oop5/variance.xml
M language/types.xml
M language/types/boolean.xml
M language/types/declarations.xml
M language/types/integer.xml
M language/types/iterable.xml
M language/types/null.xml
M language/types/string.xml
M language/types/type-juggling.xml
Diff:
diff --git a/appendices/migration81/new-features.xml \
b/appendices/migration81/new-features.xml index 6bece3fd4f2..b84f5ddf34c 100644
--- a/appendices/migration81/new-features.xml
+++ b/appendices/migration81/new-features.xml
@@ -105,12 +105,12 @@ $arr2 = [...$arr1, 'c' => 'd']; //[1, 'a' => 'b', 'c' => 'd']
<title>Intersection Types</title>
<para>
- Support for <link \
linkend="language.types.declarations.composite.intersection">intersection \
types</link> has been added. + Support for <link \
linkend="language.types.type-system.composite.intersection">intersection types</link> \
has been added. <!-- RFC: https://wiki.php.net/rfc/pure-intersection-types -->
</para>
<caution>
<simpara>
- <link linkend="language.types.declarations.composite.intersection">
+ <link linkend="language.types.type-system.composite.intersection">
Intersection types</link> cannot be used together with
<link linkend="language.types.declarations.composite.union">
union types</link>
diff --git a/language/oop5/properties.xml b/language/oop5/properties.xml
index bee74c5cd61..cb0d4ef63db 100644
--- a/language/oop5/properties.xml
+++ b/language/oop5/properties.xml
@@ -222,7 +222,7 @@ $test->prop = "foobar";
<note>
<para>
The readonly modifier can only be applied to <link \
linkend="language.oop5.properties.typed-properties">typed \
properties</link>.
- A readonly property without type constraints can be created using the <xref \
linkend="language.types.declarations.mixed" /> type. + A readonly property \
without type constraints can be created using the <xref \
linkend="language.types.mixed"/> type. </para>
</note>
<note>
diff --git a/language/oop5/variance.xml b/language/oop5/variance.xml
index 7f4ddde0876..61ad7271f7a 100644
--- a/language/oop5/variance.xml
+++ b/language/oop5/variance.xml
@@ -19,13 +19,13 @@
<listitem>
<simpara>
A type is removed from a
- <link linkend="language.types.declarations.composite.union">union type</link>
+ <link linkend="language.types.type-system.composite.union">union type</link>
</simpara>
</listitem>
<listitem>
<simpara>
A type is added to an
- <link linkend="language.types.declarations.composite.intersection">intersection \
type</link> + <link \
linkend="language.types.type-system.composite.intersection">intersection type</link> \
</simpara> </listitem>
<listitem>
diff --git a/language/types.xml b/language/types.xml
index 753d08e791a..8009e0b7745 100644
--- a/language/types.xml
+++ b/language/types.xml
@@ -5,177 +5,136 @@
<sect1 xml:id="language.types.intro">
<title>Introduction</title>
-
- <simpara>
- PHP supports ten primitive types.
- </simpara>
-
+
<para>
- Four scalar types:
+ Every single expression in PHP has one of the following
+ built-in types depending on its value:
+ <itemizedlist>
+ <listitem><simpara><type>null</type></simpara></listitem>
+ <listitem><simpara><type>bool</type></simpara></listitem>
+ <listitem><simpara><type>int</type></simpara></listitem>
+ <listitem><simpara><type>float</type> (floating-point \
number)</simpara></listitem> + \
<listitem><simpara><type>string</type></simpara></listitem> + \
<listitem><simpara><type>array</type></simpara></listitem> + \
<listitem><simpara><type>object</type></simpara></listitem> + \
<listitem><simpara><type>callable</type></simpara></listitem> + \
<listitem><simpara><type>resource</type></simpara></listitem> + </itemizedlist>
</para>
- <itemizedlist>
-
- <listitem>
- <simpara>
- <type>bool</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>int</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>float</type> (floating-point number)
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>string</type>
- </simpara>
- </listitem>
-
- </itemizedlist>
-
<para>
- Four compound types:
+ PHP is a dynamically typed language, which means that by default there is
+ no need to specify the type of a variable, as this will be determined at
+ runtime. However, it is possible to statically type some aspect of the
+ language via the use of
+ <link linkend="language.types.declarations">type declarations</link>.
</para>
- <itemizedlist>
-
- <listitem>
- <simpara>
- <type>array</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>object</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>callable</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>iterable</type>
- </simpara>
- </listitem>
-
- </itemizedlist>
-
<para>
- And finally two special types:
+ Types restrict the kind of operations that can be performed on them.
+ However, if an expression/variable is used in an operation which
+ its type does not support, PHP will attempt to
+ <link linkend="language.types.type-juggling">type juggle</link>
+ the value into a type that supports the operation.
+ This process depends on the context in which the value is used.
+ For more information, see the section on
+ <link linkend="language.types.type-juggling">Type Juggling</link>.
</para>
- <itemizedlist>
-
- <listitem>
- <simpara>
- <type>resource</type>
- </simpara>
- </listitem>
-
- <listitem>
- <simpara>
- <type>NULL</type>
- </simpara>
- </listitem>
-
- </itemizedlist>
+ <tip>
+ <simpara>
+ <link linkend="types.comparisons">The type comparison tables</link>
+ may also be useful, as various examples of comparison between values of
+ different types are present.
+ </simpara>
+ </tip>
- <simpara>
- The type of a variable is not usually set by the programmer; rather, it is
- decided at runtime by PHP depending on the context in which that variable is
- used.
- </simpara>
-
<note>
<simpara>
- To check the type and value of an
- <link linkend="language.expressions">expression</link>, use the
- <function>var_dump</function> function.
+ It is possible to force an expression to be evaluated to a certain type by
+ using a <link linkend="language.types.typecasting">type cast</link>.
+ A variable can also be type cast in-place by using the
+ <function>settype</function> function on it.
</simpara>
+ </note>
+
+ <para>
+ To check the value and type of an
+ <link linkend="language.expressions">expression</link>,
+ use the <function>var_dump</function> function.
+ To retrieve the type of an
+ <link linkend="language.expressions">expression</link>,
+ use the <function>get_debug_type</function> function.
+ However, to check if an expression is of a certain type use the
+ <!-- TODO When PhD support is there: \
<function>is_<replaceable>type</replaceable></function> --> + \
<literal>is_<replaceable>type</replaceable></literal> functions instead.
- <para>
- To get a human-readable representation of a type for debugging, use the
- <function>gettype</function> function. To check for a certain type, do
- <emphasis>not</emphasis> use <function>gettype</function>, but rather the
- <literal>is_<replaceable>type</replaceable></literal> functions. Some
- examples:
- </para>
-
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
-$a_bool = TRUE; // a boolean
+$a_bool = true; // a bool
$a_str = "foo"; // a string
$a_str2 = 'foo'; // a string
-$an_int = 12; // an integer
+$an_int = 12; // an int
-echo gettype($a_bool); // prints out: boolean
-echo gettype($a_str); // prints out: string
+echo get_debug_type($a_bool), "\n";
+echo get_debug_type($a_str), "\n";
// If this is an integer, increment it by four
if (is_int($an_int)) {
$an_int += 4;
}
+var_dump($an_int);
// If $a_bool is a string, print it out
-// (does not print out anything)
if (is_string($a_bool)) {
echo "String: $a_bool";
}
?>
]]>
</programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+bool
+string
+int(16)
+]]>
+ </screen>
</informalexample>
+ </para>
+ <note>
+ <simpara>
+ Prior to PHP 8.0.0, where the <function>get_debug_type</function> is not
+ available, the <function>gettype</function> function can be used instead.
+ However, it doesn't use the canonical type names.
+ </simpara>
</note>
-
- <simpara>
- To forcibly convert a variable to a certain type, either
- <link linkend="language.types.typecasting">cast</link> the variable or use
- the <function>settype</function> function on it.
- </simpara>
-
- <simpara>
- Note that a variable may be evaluated with different values in certain
- situations, depending on what type it is at the time. For more information,
- see the section on <link linkend="language.types.type-juggling">Type
- Juggling</link>. <link linkend="types.comparisons">The type comparison
- tables</link> may also be useful, as they show examples of various
- type-related comparisons.
- </simpara>
</sect1>
-
+
+ &language.types.type-system;
+ &language.types.null;
&language.types.boolean;
&language.types.integer;
&language.types.float;
&language.types.string;
&language.types.numeric-strings;
&language.types.array;
- &language.types.iterable;
&language.types.object;
&language.types.enumerations;
&language.types.resource;
- &language.types.null;
&language.types.callable;
+ &language.types.mixed;
+ &language.types.void;
+ &language.types.never;
+ &language.types.relative-class-types;
+ &language.types.literal;
+ &language.types.iterable;
&language.types.declarations;
&language.types.type-juggling;
-
+
</chapter>
-
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
diff --git a/language/types/boolean.xml b/language/types/boolean.xml
index 097c8e02a6f..61073f3c7b8 100644
--- a/language/types/boolean.xml
+++ b/language/types/boolean.xml
@@ -4,8 +4,8 @@
<title>Booleans</title>
<simpara>
- This is the simplest type. A <type>bool</type> expresses a truth value. It
- can be either &true; or &false;.
+ The <type>bool</type> type only has two values, and is used to express
+ a truth value. It can be either &true; or &false;.
</simpara>
<sect2 xml:id="language.types.boolean.syntax">
@@ -61,14 +61,10 @@ if ($show_separators) {
<simpara>
To explicitly convert a value to <type>bool</type>, use the
- <literal>(bool)</literal> or <literal>(boolean)</literal> casts. However, in
- most cases the cast is unnecessary, since a value will be automatically
- converted if an operator, function or control structure requires a
- <type>bool</type> argument.
- </simpara>
-
- <simpara>
- See also <link linkend="language.types.type-juggling">Type Juggling</link>.
+ <literal>(bool)</literal> cast. Generally this is not necessary because when
+ a value is used in a logical context it will be automatically interpreted
+ as a value of type <type>bool</type>. For more information see the
+ <link linkend="language.types.type-juggling">Type Juggling</link> page.
</simpara>
<para>
@@ -84,18 +80,20 @@ if ($show_separators) {
</listitem>
<listitem>
<simpara>
- the <link linkend="language.types.integer">integer</link> 0 (zero)
+ the <link linkend="language.types.integer">integer</link>
+ <literal>0</literal> (zero)
</simpara>
</listitem>
<listitem>
<simpara>
- the <link linkend="language.types.float">float</link>s 0.0 and -0.0 (zero)
+ the <link linkend="language.types.float">float</link>s
+ <literal>0.0</literal> and <literal>-0.0</literal> (zero)
</simpara>
</listitem>
<listitem>
<simpara>
- the empty <link linkend="language.types.string">string</link>, and the
- <link linkend="language.types.string">string</link> "0"
+ the empty <link linkend="language.types.string">string</link> \
<literal>""</literal>, + and the <link \
linkend="language.types.string">string</link> <literal>"0"</literal> </simpara>
</listitem>
<listitem>
@@ -105,21 +103,23 @@ if ($show_separators) {
</listitem>
<listitem>
<simpara>
- the special type <link linkend="language.types.null">NULL</link> (including
+ the unit type <link linkend="language.types.null">NULL</link> (including
unset variables)
</simpara>
</listitem>
<listitem>
<simpara>
- <link linkend="ref.simplexml">SimpleXML</link> objects created from \
attributeless
- empty elements, i.e. elements which have neither children nor attributes.
+ Internal objects that overload their casting behaviour to bool.
+ For example: <link linkend="ref.simplexml">SimpleXML</link> objects
+ created from empty elements without attributes.
</simpara>
</listitem>
</itemizedlist>
<para>
- Every other value is considered &true; (including any
- <link linkend="language.types.resource">resource</link> and \
<constant>NAN</constant>). + Every other value is considered &true;
+ (including <link linkend="language.types.resource">resource</link>
+ and <constant>NAN</constant>).
</para>
<warning>
@@ -149,7 +149,6 @@ var_dump((bool) "false"); // bool(true)
</sect2>
</sect1>
-
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
diff --git a/language/types/declarations.xml b/language/types/declarations.xml
index 51cf4cb480c..beac582d229 100644
--- a/language/types/declarations.xml
+++ b/language/types/declarations.xml
@@ -10,130 +10,136 @@
<classname>TypeError</classname> is thrown.
</para>
- <!-- Find better place where to put this note -->
+ <para>
+ Every single type that PHP supports, with the exception of
+ <type>resource</type> can be used within a user-land type declaration.
+ This page contains a changelog of availability of the different types
+ and documentation about usage of them in type declarations.
+ </para>
+
<note>
- <!-- TODO Link to covariance section -->
<para>
- When overriding a parent method, the child's method must match any return
- type declaration on the parent. If the parent doesn't define a return
- type, then the child method may do so.
+ When a class implements an interface method or reimplements a method which
+ has already been defined by a parent class, it has to be compatible with the
+ aforementioned definition.
+ A method is compatible if it follows the
+ <link linkend="language.oop5.variance">variance</link> rules.
</para>
</note>
- <sect2 xml:id="language.types.declarations.base">
- <title>Single types</title>
+ <sect2 role="changelog">
+ &reftitle.changelog;
<informaltable>
- <tgroup cols="3">
+ <tgroup cols="2">
<thead>
<row>
- <entry>&Type;</entry>
- <entry>&Description;</entry>
<entry>&Version;</entry>
+ <entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
- <entry>Class/interface name</entry>
+ <entry>8.2.0</entry>
<entry>
- The value must be an &instanceof; the given class or interface.
+ Support for <acronym>DNF</acronym> types has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>self</type></entry>
+ <entry>8.2.0</entry>
<entry>
- The value must be an &instanceof; the same class as the one
- in which the type declaration is used.
- Can only be used in classes.
+ Support for the literal type <type>true</type> has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>parent</type></entry>
+ <entry>8.2.0</entry>
<entry>
- The value must be an &instanceof; the parent of the class
- in which the type declaration is used.
- Can only be used in classes.
+ The types <type>null</type> and <type>false</type> can now be used \
standalone. </entry>
- <entry/>
</row>
<row>
- <entry><type>array</type></entry>
+ <entry>8.1.0</entry>
<entry>
- The value must be an <type>array</type>.
+ Support for intersection types has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>callable</type></entry>
+ <entry>8.1.0</entry>
<entry>
- The value must be a valid <type>callable</type>.
- Cannot be used as a class property type declaration.
+ Returning by reference from a <type>void</type> function is now deprecated.
</entry>
- <entry/>
</row>
<row>
- <entry><type>bool</type></entry>
+ <entry>8.1.0</entry>
<entry>
- The value must be a boolean value.
+ Support for the return only type <type>never</type> has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>float</type></entry>
+ <entry>8.0.0</entry>
<entry>
- The value must be a floating point number.
+ Support for <type>mixed</type> has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>int</type></entry>
+ <entry>8.0.0</entry>
<entry>
- The value must be an integer.
+ Support for the return only type <type>static</type> has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>string</type></entry>
+ <entry>8.0.0</entry>
<entry>
- The value must be a <type>string</type>.
+ Support for union types has been added.
</entry>
- <entry/>
</row>
<row>
- <entry><type>iterable</type></entry>
+ <entry>7.2.0</entry>
<entry>
- The value must be either an <type>array</type> or an &instanceof; \
<classname>Traversable</classname>. + Support for <type>object</type> has been \
added. </entry>
- <entry>PHP 7.1.0</entry>
</row>
<row>
- <entry><type>object</type></entry>
+ <entry>7.1.0</entry>
<entry>
- The value must be an <type>object</type>.
+ Support for <type>iterable</type> has been added.
</entry>
- <entry>PHP 7.2.0</entry>
</row>
<row>
- <entry><type>mixed</type></entry>
+ <entry>7.1.0</entry>
<entry>
- The value can be any value.
+ Support for <type>void</type> has been added.
+ </entry>
+ </row>
+ <row>
+ <entry>7.1.0</entry>
+ <entry>
+ Support for nullable types has been added.
</entry>
- <entry>PHP 8.0.0</entry>
</row>
</tbody>
</tgroup>
</informaltable>
+ </sect2>
- <warning>
- <para>
- Aliases for the above scalar types are not supported.
- Instead, they are treated as class or interface names.
- For example, using <literal>boolean</literal> as a type declaration
- will require the value to be an &instanceof; the class or interface
- <literal>boolean</literal>, rather than of type <type>bool</type>:
- </para>
- <para>
+ <sect2 xml:id="language.types.declarations.base">
+ <title>Base Types Usage Notes</title>
+
+ <simpara>
+ Base types have straight forward behaviour with some minor caveats which
+ are described in this section.
+ </simpara>
+
+ <sect3 xml:id="language.types.declarations.base.scalar">
+ <title>Scalar types</title>
+ <warning>
+ <para>
+ Name aliases for scalar types (<type>bool</type>, <type>int</type>,
+ <type>float</type>, <type>string</type>) are not supported.
+ Instead, they are treated as class or interface names.
+ For example, using <literal>boolean</literal> as a type declaration
+ will require the value to be an &instanceof; the class or interface
+ <literal>boolean</literal>, rather than of type <type>bool</type>:
+ </para>
<example>
<programlisting role="php">
<![CDATA[
@@ -156,205 +162,147 @@ Stack trace:
]]>
</screen>
</example>
- </para>
- </warning>
-
- <sect3 xml:id="language.types.declarations.mixed">
- <title>mixed</title>
+ </warning>
+ </sect3>
- <para>
- <type>mixed</type> is equivalent to the <link \
linkend="language.types.declarations.composite.union">union \
type</link>
- <type class="union">
- <type>object</type><type>resource</type><type>array</type><type>string</type>
- <type>int</type><type>float</type><type>bool</type><type>null</type>
- </type>.
- Available as of PHP 8.0.0.
- </para>
- </sect3>
+ <sect3 xml:id="language.types.declarations.void">
+ <title>void</title>
+ <note>
+ <para>
+ Returning by reference from a <type>void</type> function is deprecated as of \
PHP 8.1.0, + because such a function is contradictory.
+ Previously, it already emitted the following
+ <constant>E_NOTICE</constant> when called:
+ <literal>Only variable references should be returned by reference</literal>.
- <sect3 xml:id="language.types.declarations.examples">
- &reftitle.examples;
- <example>
- <title>Basic class type declaration</title>
- <programlisting role="php">
+ <informalexample>
+ <programlisting role="php">
<![CDATA[
<?php
-class C {}
-class D extends C {}
-
-// This doesn't extend C.
-class E {}
-
-function f(C $c) {
- echo get_class($c)."\n";
-}
-
-f(new C);
-f(new D);
-f(new E);
+function &test(): void {}
?>
]]>
- </programlisting>
- &example.outputs.8;
- <screen>
-<![CDATA[
-C
-D
-
-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
-Stack trace:
-#0 -(14): f(Object(E))
-#1 {main}
- thrown in - on line 8
-]]>
- </screen>
- </example>
-
- <example>
- <title>Basic interface type declaration</title>
- <programlisting role="php">
-<![CDATA[
-<?php
-interface I { public function f(); }
-class C implements I { public function f() {} }
+ </programlisting>
+ </informalexample>
+ </para>
+ </note>
+ </sect3>
-// This doesn't implement I.
-class E {}
+ <sect3 xml:id="language.types.declarations.base.function">
+ <title>Callable types</title>
+ <para>
+ This type cannot be used as a class property type declaration.
+ </para>
-function f(I $i) {
- echo get_class($i)."\n";
-}
+ <note>
+ <simpara>
+ It is not possible to specify the signature of the function.
+ </simpara>
+ </note>
+ </sect3>
-f(new C);
-f(new E);
-?>
-]]>
- </programlisting>
- &example.outputs.8;
- <screen>
-<![CDATA[
-C
-
-Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, \
called in - on line 13 and defined in -:8
-Stack trace:
-#0 -(13): f(Object(E))
-#1 {main}
- thrown in - on line 8
-]]>
- </screen>
- </example>
+ <sect3 xml:id="language.types.declarations.references">
+ <title>Type declarations on pass-by-reference Parameters</title>
+ <simpara>
+ If a pass-by-reference parameter has a type declaration, the type of the
+ variable is <emphasis>only</emphasis> checked on function entry, at the
+ beginning of the call, but not when the function returns.
+ This means that a function can change the type of variable reference.
+ </simpara>
<example>
- <title>Basic return type declaration</title>
+ <title>Typed pass-by-reference Parameters</title>
<programlisting role="php">
<![CDATA[
<?php
-function sum($a, $b): float {
- return $a + $b;
+function array_baz(array &$param)
+{
+ $param = 1;
}
-
-// Note that a float will be returned.
-var_dump(sum(1, 2));
+$var = [];
+array_baz($var);
+var_dump($var);
+array_baz($var);
?>
]]>
</programlisting>
- &example.outputs;
+ &example.outputs.similar;
<screen>
<![CDATA[
-float(3)
-]]>
- </screen>
- </example>
-
- <example>
- <title>Returning an object</title>
- <programlisting role="php">
-<![CDATA[
-<?php
-class C {}
-
-function getC(): C {
- return new C;
-}
+int(1)
-var_dump(getC());
-?>
-]]>
- </programlisting>
- &example.outputs;
- <screen>
-<![CDATA[
-object(C)#1 (0) {
-}
+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 +Stack trace:
+#0 -(9): array_baz(1)
+#1 {main}
+ thrown in - on line 2
]]>
</screen>
</example>
</sect3>
</sect2>
- <sect2 xml:id="language.types.declarations.nullable">
- <title>Nullable type</title>
-
+ <sect2 xml:id="language.types.declarations.composite">
+ <title>Composite Types Usage Notes</title>
<para>
- As of PHP 7.1.0, type declarations can be marked nullable by prefixing the
- type name with a question mark (<literal>?</literal>).
- This signifies that the value can be of the specified type or &null;.
+ Composite type declarations are subject to a couple of restrictions and
+ will perform a redundancy check at compile time to prevent simple bugs.
</para>
- <para>
- <example>
- <title>Nullable argument type declaration</title>
- <programlisting role="php">
-<![CDATA[
-<?php
-class C {}
+ <caution>
+ <simpara>
+ Prior to PHP 8.2.0, and the introduction of <acronym>DNF</acronym> types,
+ it was not possible to combine intersection types with union types.
+ </simpara>
+ </caution>
-function f(?C $c) {
- var_dump($c);
-}
+ <sect3 xml:id="language.types.declarations.composite.union">
+ <title>Union types</title>
+ <warning>
+ <simpara>
+ It is not possible to combine the two literal types <literal>false</literal>
+ and <literal>true</literal> together in a union type.
+ Use <type>bool</type> instead.
+ </simpara>
+ </warning>
-f(new C);
-f(null);
-?>
-]]>
- </programlisting>
- &example.outputs;
- <screen>
-<![CDATA[
-object(C)#1 (0) {
-}
-NULL
-]]>
- </screen>
- </example>
+ <caution>
+ <simpara>
+ Prior to PHP 8.2.0, as <literal>false</literal> and <type>null</type>
+ could not be used as standalone types, a union type comprised of only
+ these types was not permitted. This comprises the following types:
+ <literal>false</literal>, <literal>false|null</literal>,
+ and <literal>?false</literal>.
+ </simpara>
+ </caution>
- <example>
- <title>Nullable return type declaration</title>
- <programlisting role="php">
-<![CDATA[
-<?php
-function get_item(): ?string {
- if (isset($_GET['item'])) {
- return $_GET['item'];
- } else {
- return null;
- }
-}
-?>
-]]>
- </programlisting>
- </example>
- </para>
+ <sect4 xml:id="language.types.declarations.nullable">
+ <title>Nullable type syntactic sugar</title>
- <note>
- <para>
- It is possible to achieve nullable arguments by making
- <literal>null</literal> the default value.
- This is not recommended as this breaks during inheritance.
- </para>
- <example>
- <title>Old way to make arguments nullable</title>
- <programlisting role="php">
+ <para>
+ A single base type declaration can be marked nullable by prefixing the
+ type with a question mark (<literal>?</literal>).
+ Thus <literal>?T</literal> and <literal>T|null</literal> are identical.
+ </para>
+
+ <note>
+ <simpara>
+ This syntax is supported as of PHP 7.1.0, and predates generalized union
+ types support.
+ </simpara>
+ </note>
+
+ <note>
+ <para>
+ It is also possible to achieve nullable arguments by making
+ <literal>null</literal> the default value.
+ This is not recommended as if the default value is changed in a child
+ class a type compatibility violation will be raised as the
+ <type>null</type> type will need to be added to the type declaration.
+ </para>
+ <example>
+ <title>Old way to make arguments nullable</title>
+ <programlisting role="php">
<![CDATA[
<?php
class C {}
@@ -367,104 +315,18 @@ f(new C);
f(null);
?>
]]>
- </programlisting>
- &example.outputs;
- <screen>
+ </programlisting>
+ &example.outputs;
+ <screen>
<![CDATA[
object(C)#1 (0) {
}
NULL
]]>
- </screen>
- </example>
- </note>
- </sect2>
-
- <sect2 xml:id="language.types.declarations.composite">
- <title>Composite types</title>
- <para>
- It is possible to combine simple types into composite types.
- PHP allows types to be combined in the following ways:
- </para>
-
- <itemizedlist>
- <listitem>
- <simpara>
- Union of simple types. As of PHP 8.0.0.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Intersection of class-types (interfaces and class names). As of PHP 8.1.0.
- </simpara>
- </listitem>
- </itemizedlist>
-
- <caution>
- <simpara>
- It is not possible to combine intersection types with union types.
- </simpara>
- </caution>
-
- <sect3 xml:id="language.types.declarations.composite.union">
- <title>Union types</title>
- <para>
- A union type declaration accepts values of multiple different simple types,
- rather than a single one.
- Union types are specified using the syntax <literal>T1|T2|...</literal>.
- Union types are available as of PHP 8.0.0.
- </para>
-
- <sect4 xml:id="language.types.declarations.composite.union.nullable">
- <title>Nullable union types</title>
- <para>
- The <literal>null</literal> type is supported as part of unions,
- such that <literal>T1|T2|null</literal> can be used to create a nullable union.
- The existing <literal>?T</literal> notation is considered a shorthand
- for the common case of <literal>T|null</literal>.
- </para>
-
- <caution>
- <simpara>
- <literal>null</literal> cannot be used as a standalone type.
- </simpara>
- </caution>
+ </screen>
+ </example>
+ </note>
</sect4>
-
- <sect4 xml:id="language.types.declarations.composite.union.false">
- <title>false pseudo-type</title>
- <para>
- The <literal>false</literal> literal type is supported as part of unions,
- and is included as for historical reasons many internal functions return
- <literal>false</literal> instead of <literal>null</literal> for failures.
- A classic example of such a function is <function>strpos</function>.
- </para>
-
- <caution>
- <simpara>
- <literal>false</literal> cannot be used as a standalone type (including
- nullable standalone type).
- As such, <literal>false</literal>, <literal>false|null</literal>
- and <literal>?false</literal> are not permitted.
- </simpara>
- </caution>
- <caution>
- <simpara>
- The <literal>true</literal> literal type does <emphasis>not</emphasis>
- exist.
- </simpara>
- </caution>
- </sect4>
- </sect3>
-
- <sect3 xml:id="language.types.declarations.composite.intersection">
- <title>Intersection types</title>
- <para>
- An intersection type declaration accepts values which satisfies multiple
- class-type declarations, rather than a single one.
- Intersection types are specified using the syntax \
<literal>T1&T2&...</literal>.
- Intersection types are available as of PHP 8.1.0.
- </para>
</sect3>
<sect3 xml:id="language.types.declarations.composite.redundant">
@@ -493,7 +355,8 @@ NULL
<itemizedlist>
<listitem>
<simpara>
- If <type>bool</type> is used, <type>false</type> cannot be used \
additionally. + If <type>bool</type> is used, <type>false</type> or \
<type>true</type> + cannot be used additionally.
</simpara>
</listitem>
<listitem>
@@ -525,6 +388,21 @@ NULL
</listitem>
</itemizedlist>
</listitem>
+ <listitem>
+ <simpara>For <acronym>DNF</acronym> types:</simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ If a more generic type is used, the more restrictive one is redundant.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Using two identical intersection types.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </listitem>
</itemizedlist>
</para>
@@ -568,64 +446,169 @@ function foo(): X&Y {} // Allowed (redundancy is only known at \
runtime) </sect3>
</sect2>
- <sect2 xml:id="language.types.declarations.return-only">
- <title>Return only types</title>
+ <sect2 xml:id="language.types.declarations.examples">
+ &reftitle.examples;
+ <example>
+ <title>Basic class type declaration</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+class D extends C {}
- <sect3 xml:id="language.types.declarations.void">
- <title>void</title>
- <para>
- <literal>void</literal> is a return type indicating the function does not
- return a value.
- Therefore it cannot be part of a union type declaration.
- Available as of PHP 7.1.0.
- </para>
- <note>
- <para>
- Returning by reference from a <type>void</type> function is deprecated as of \
PHP 8.1.0,
- because such a function is contradictory.
- Previously, it already emitted the following
- <constant>E_NOTICE</constant> when called:
- <literal>Only variable references should be returned by reference</literal>.
+// This doesn't extend C.
+class E {}
- <informalexample>
- <programlisting role="php">
+function f(C $c) {
+ echo get_class($c)."\n";
+}
+
+f(new C);
+f(new D);
+f(new E);
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+C
+D
+
+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 +Stack trace:
+#0 -(14): f(Object(E))
+#1 {main}
+ thrown in - on line 8
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Basic interface type declaration</title>
+ <programlisting role="php">
<![CDATA[
<?php
-function &test(): void {}
+interface I { public function f(); }
+class C implements I { public function f() {} }
+
+// This doesn't implement I.
+class E {}
+
+function f(I $i) {
+ echo get_class($i)."\n";
+}
+
+f(new C);
+f(new E);
?>
]]>
- </programlisting>
- </informalexample>
- </para>
- </note>
- </sect3>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+C
- <sect3 xml:id="language.types.declarations.never">
- <title>never</title>
- <para>
- <literal>never</literal> is a return type indicating the function does not
- return. This means that it either calls <function>exit</function>, throws
- an exception, or is an infinite loop.
- Therefore it cannot be part of a union type declaration.
- Available as of PHP 8.1.0.
- </para>
- <para>
- <type>never</type> is, in type theory parlance, the bottom type.
- Meaning it is the subtype of every other type and can replace any other
- return type during inheritance.
- </para>
- </sect3>
+Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, \
called in - on line 13 and defined in -:8 +Stack trace:
+#0 -(13): f(Object(E))
+#1 {main}
+ thrown in - on line 8
+]]>
+ </screen>
+ </example>
- <sect3 xml:id="language.types.declarations.static">
- <title>static</title>
- <para>
- The value must be an &instanceof; the same class as the one the
- method is called in.
- Available as of PHP 8.0.0.
- </para>
- </sect3>
+ <example>
+ <title>Basic return type declaration</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function sum($a, $b): float {
+ return $a + $b;
+}
+
+// Note that a float will be returned.
+var_dump(sum(1, 2));
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+float(3)
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Returning an object</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+
+function getC(): C {
+ return new C;
+}
+
+var_dump(getC());
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+object(C)#1 (0) {
+}
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Nullable argument type declaration</title>
+ <programlisting role="php">
+ <![CDATA[
+<?php
+class C {}
+
+function f(?C $c) {
+ var_dump($c);
+}
+
+f(new C);
+f(null);
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+ <![CDATA[
+object(C)#1 (0) {
+}
+NULL
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Nullable return type declaration</title>
+ <programlisting role="php">
+ <![CDATA[
+<?php
+function get_item(): ?string {
+ if (isset($_GET['item'])) {
+ return $_GET['item'];
+ } else {
+ return null;
+ }
+}
+?>
+]]>
+ </programlisting>
+ </example>
</sect2>
+ <!-- TODO Move this into its own declare page -->
<sect2 xml:id="language.types.declarations.strict">
<title>Strict typing</title>
@@ -759,161 +742,7 @@ Stack trace:
</example>
</sect2>
- <sect2 xml:id="language.types.declarations.union.coercive">
- <title>Coercive typing with union types</title>
- <para>
- When <literal>strict_types</literal> is not enabled, scalar type declarations
- are subject to limited implicit type coercions.
- If the exact type of the value is not part of the union, then the target type
- is chosen in the following order of preference:
-
- <orderedlist>
- <listitem>
- <simpara>
- <type>int</type>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <type>float</type>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <type>string</type>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <type>bool</type>
- </simpara>
- </listitem>
- </orderedlist>
-
- If the type both exists in the union, and the value can be coerced to the
- type under PHPs existing type checking semantics, then the type is chosen.
- Otherwise the next type is tried.
- </para>
-
- <caution>
- <para>
- As an exception, if the value is a string and both int and float are part
- of the union, the preferred type is determined by the existing
- "numeric string" semantics.
- For example, for <literal>"42"</literal> <type>int</type> is chosen,
- while for <literal>"42.0"</literal> <type>float</type> is chosen.
- </para>
- </caution>
-
- <note>
- <para>
- Types that are not part of the above preference list are not eligible
- targets for implicit coercion. In particular no implicit coercions to
- the <literal>null</literal> and <literal>false</literal> types occur.
- </para>
- </note>
-
- <example>
- <title>Example of types being coerced into a type part of the union</title>
- <programlisting role="php">
-<![CDATA[
-<?php
-// int|string
-42 --> 42 // exact type
-"42" --> "42" // exact type
-new ObjectWithToString --> "Result of __toString()"
- // object never compatible with int, fall back to string
-42.0 --> 42 // float compatible with int
-42.1 --> 42 // float compatible with int
-1e100 --> "1.0E+100" // float too large for int type, fall back to string
-INF --> "INF" // float too large for int type, fall back to string
-true --> 1 // bool compatible with int
-[] --> TypeError // array not compatible with int or string
-
-// int|float|bool
-"45" --> 45 // int numeric string
-"45.0" --> 45.0 // float numeric string
-
-"45X" --> true // not numeric string, fall back to bool
-"" --> false // not numeric string, fall back to bool
-"X" --> true // not numeric string, fall back to bool
-[] --> TypeError // array not compatible with int, float or bool
-?>
-]]>
- </programlisting>
- </example>
- </sect2>
-
-<!-- TODO figure out what do to with these things -->
- <sect2 xml:id="language.types.declarations.misc">
- <title>Misc</title>
- <example>
- <title>Typed pass-by-reference Parameters</title>
- <simpara>
- Declared types of reference parameters are checked on function entry, but
- not when the function returns, so after the function had returned, the
- argument's type may have changed.
- </simpara>
- <programlisting role="php">
-<![CDATA[
-<?php
-function array_baz(array &$param)
-{
- $param = 1;
-}
-$var = [];
-array_baz($var);
-var_dump($var);
-array_baz($var);
-?>
-]]>
- </programlisting>
- &example.outputs.8;
- <screen>
-<![CDATA[
-int(1)
-
-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
-Stack trace:
-#0 -(9): array_baz(1)
-#1 {main}
- thrown in - on line 2
-]]>
- </screen>
- </example>
-
- <example>
- <title>Catching <classname>TypeError</classname></title>
- <programlisting role="php">
-<![CDATA[
-<?php
-declare(strict_types=1);
-
-function sum(int $a, int $b) {
- return $a + $b;
-}
-
-try {
- var_dump(sum(1, 2));
- var_dump(sum(1.5, 2.5));
-} catch (TypeError $e) {
- echo 'Error: ', $e->getMessage();
-}
-?>
-]]>
- </programlisting>
- &example.outputs.8;
- <screen>
-<![CDATA[
-int(3)
-Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line \
10
-]]>
- </screen>
- </example>
- </sect2>
-
</sect1>
-
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
diff --git a/language/types/integer.xml b/language/types/integer.xml
index cc2f9019b81..508f7367399 100644
--- a/language/types/integer.xml
+++ b/language/types/integer.xml
@@ -8,33 +8,22 @@
ℤ = {..., -2, -1, 0, 1, 2, ...}.
</simpara>
- <para>
- See also:
- </para>
-
- <itemizedlist>
- <listitem>
- <simpara>
- <link linkend="book.gmp">Arbitrary length integer / GMP</link>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <link linkend="language.types.float">Floating point numbers</link>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <link linkend="book.bc">Arbitrary precision / BCMath</link>
- </simpara>
- </listitem>
- </itemizedlist>
+ <sect2 role="seealso">
+ &reftitle.seealso;
+ <para>
+ <simplelist>
+ <member><link linkend="language.types.float">Floating point \
numbers</link></member> + <member><link linkend="book.bc">Arbitrary precision / \
BCMath</link></member> + <member><link linkend="book.gmp">Arbitrary length integer \
/ GMP</link></member> + </simplelist>
+ </para>
+ </sect2>
<sect2 xml:id="language.types.integer.syntax">
<title>Syntax</title>
<simpara>
- <type>int</type>s can be specified in decimal (base 10), hexadecimal
+ <type>Int</type>s can be specified in decimal (base 10), hexadecimal
(base 16), octal (base 8) or binary (base 2) notation.
The <link linkend="language.operators.arithmetic">negation operator</link>
can be used to denote a negative <type>int</type>.
@@ -69,8 +58,10 @@ $a = 1_234_567; // decimal number (as of PHP 7.4.0)
</example>
<para>
- Formally, the structure for <type>int</type> literals is as of PHP 7.4.0
- (previously, underscores have not been allowed):
+ Formally, the structure for <type>int</type> literals is as of PHP 8.1.0
+ (previously, the <literal>0o</literal> or <literal>0O</literal> octal
+ prefixes were not allowed, and prior to PHP 7.4.0 the underscores were
+ not allowed):
</para>
<informalexample>
diff --git a/language/types/iterable.xml b/language/types/iterable.xml
index e7d9533ff75..5539da5682a 100644
--- a/language/types/iterable.xml
+++ b/language/types/iterable.xml
@@ -4,107 +4,30 @@
<title>Iterables</title>
<para>
- <type>Iterable</type> is a pseudo-type introduced in PHP 7.1. It accepts any
- &array; or object implementing the <classname>Traversable</classname>
- interface. Both of these types are iterable using &foreach; and can be used
- with <command>yield from</command> within a <link
- linkend="language.generators">generator</link>.
+ <type>Iterable</type> is a built-in compile time type alias for
+ <!-- Need to improve rendering of free-standing type elements in PhD
+ <type class="union"><type>array</type><type>Traversable</type></type>.
+ -->
+ <literal>array|Traversable</literal>.
+ From its introduction in PHP 7.1.0 and prior to PHP 8.2.0,
+ <type>iterable</type> was a built-in pseudo-type that acted as the
+ aforementioned type alias and can be used as a type declaration.
+ An iterable type can be used in &foreach; and with
+ <command>yield from</command> within a
+ <link linkend="language.generators">generator</link>.
</para>
- <sect2 xml:id="language.types.iterable.using">
- <title>Using Iterables</title>
-
- <para>
- Iterable can be used as a parameter type to indicate that a function
- requires a set of values, but does not care about the form of the value set
- since it will be used with &foreach;. If a value is not an array or
- instance of <classname>Traversable</classname>, a
- <classname>TypeError</classname> will be thrown.
- </para>
-
- <para>
- <example>
- <title>
- Iterable parameter type example
- </title>
- <programlisting role="php">
-<![CDATA[
-<?php
-
-function foo(iterable $iterable) {
- foreach ($iterable as $value) {
- // ...
- }
-}
-
-?>
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- Parameters declared as iterable may use &null; or an array as a default
- value.
- </para>
-
- <para>
- <example>
- <title>
- Iterable parameter default value example
- </title>
- <programlisting role="php">
-<![CDATA[
-<?php
-
-function foo(iterable $iterable = []) {
- // ...
-}
-
-?>
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- Iterable can also be used as a return type to indicate a function will
- return an iterable value. If the returned value is not an array or instance
- of <classname>Traversable</classname>, a <classname>TypeError</classname>
- will be thrown.
- </para>
-
- <para>
- <example>
- <title>
- Iterable return type example
- </title>
- <programlisting role="php">
-<![CDATA[
-<?php
-
-function bar(): iterable {
- return [1, 2, 3];
-}
-
-?>
-]]>
- </programlisting>
- </example>
- </para>
-
+ <note>
<para>
Functions declaring iterable as a return type may also be <link
linkend="language.generators">generators</link>.
- </para>
- <para>
<example>
<title>
Iterable generator return type example
</title>
<programlisting role="php">
-<![CDATA[
+ <![CDATA[
<?php
function gen(): iterable {
@@ -118,10 +41,8 @@ function gen(): iterable {
</programlisting>
</example>
</para>
- </sect2>
-
+ </note>
</sect1>
-
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
diff --git a/language/types/literal.xml b/language/types/literal.xml
new file mode 100644
index 00000000000..608d4462bb6
--- /dev/null
+++ b/language/types/literal.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.literal">
+ <title>Literal types</title>
+
+ <para>
+ Literal types are type which not only check the type of a value but also
+ the value itself. PHP has support for two literal types:
+ <literal>false</literal> as of PHP 8.0.0, and <literal>true</literal>
+ as of PHP 8.2.0.
+ </para>
+
+ <warning>
+ <simpara>
+ Prior to PHP 8.2.0 the <literal>false</literal> type could only be used as part \
of a + <link linkend="language.types.type-system.composite.union">union \
type</link>. + </simpara>
+ </warning>
+
+ <note>
+ <simpara>
+ It is not possible to define custom literal types. Consider using an
+ <link linkend="language.types.enumerations">enumerations</link> instead.
+ </simpara>
+ </note>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
diff --git a/language/types/mixed.xml b/language/types/mixed.xml
new file mode 100644
index 00000000000..3d65f66ddb2
--- /dev/null
+++ b/language/types/mixed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.mixed">
+ <title>Mixed</title>
+
+ <para>
+ The <type>mixed</type> type accepts every value. It is equivalent to the
+ <link linkend="language.types.type-system.composite.union">union type</link>
+ <!-- Need to improve rendering of free-standing type elements in PhD
+ <type class="union">
+ <type>object</type><type>resource</type><type>array</type><type>string</type>
+ <type>int</type><type>float</type><type>bool</type><type>null</type>
+ </type>.
+ -->
+ <literal>object|resource|array|string|float|int|bool|null</literal>.
+ Available as of PHP 8.0.0.
+ </para>
+
+ <para>
+ <type>mixed</type> is, in type theory parlance, the top type.
+ Meaning every other type is a subtype of it.
+ </para>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
diff --git a/language/types/never.xml b/language/types/never.xml
new file mode 100644
index 00000000000..c7b1703516c
--- /dev/null
+++ b/language/types/never.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.never">
+ <title>Never</title>
+
+ <para>
+ <type>never</type> is a return-only type indicating the function
+ does not terminate. This means that it either calls <function>exit</function>,
+ throws an exception, or is an infinite loop.
+ Therefore, it cannot be part of a
+ <link linkend="language.types.type-system.composite.union">union type</link>
+ declaration. Available as of PHP 8.1.0.
+ </para>
+ <para>
+ <type>never</type> is, in type theory parlance, the bottom type.
+ Meaning it is the subtype of every other type and can replace any other
+ return type during inheritance.
+ </para>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
diff --git a/language/types/null.xml b/language/types/null.xml
index 72cdc337ac7..b449234dbf0 100644
--- a/language/types/null.xml
+++ b/language/types/null.xml
@@ -4,31 +4,14 @@
<title>NULL</title>
<para>
- The special &null; value represents a variable with no value. &null; is the
- only possible value of type <type>null</type>.
+ The <type>null</type> type is PHP's unit type, i.e. it has only one value:
+ &null;.
</para>
<para>
- A variable is considered to be <type>null</type> if:
+ Undefined, and <function>unset</function> variables will resolve to the
+ value &null;.
</para>
-
- <itemizedlist>
- <listitem>
- <para>
- it has been assigned the constant &null;.
- </para>
- </listitem>
- <listitem>
- <para>
- it has not been set to any value yet.
- </para>
- </listitem>
- <listitem>
- <para>
- it has been <function>unset</function>.
- </para>
- </listitem>
- </itemizedlist>
<sect2 xml:id="language.types.null.syntax">
<title>Syntax</title>
@@ -47,12 +30,6 @@ $var = NULL;
]]>
</programlisting>
</informalexample>
-
- <para>
- See also the functions <function>is_null</function> and
- <function>unset</function>.
- </para>
-
</sect2>
<sect2 xml:id="language.types.null.casting">
@@ -70,8 +47,17 @@ $var = NULL;
</sect2>
+ <sect2 role="seealso">
+ &reftitle.seealso;
+ <para>
+ <simplelist>
+ <member><function>is_null</function></member>
+ <member><function>unset</function></member>
+ </simplelist>
+ </para>
+ </sect2>
+
</sect1>
-
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
diff --git a/language/types/relative-class-types.xml \
b/language/types/relative-class-types.xml new file mode 100644
index 00000000000..c91323f18e9
--- /dev/null
+++ b/language/types/relative-class-types.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.relative-class-types">
+ <title>Relative class types</title>
+
+ <para>
+ These types declarations can only be used within classes.
+ </para>
+
+ <sect2 xml:id="language.types.relative-class-types.self">
+ <title><type>self</type></title>
+ <para>
+ The value must be an &instanceof; the same class as the one
+ in which the type declaration is used.
+ </para>
+ </sect2>
+
+ <sect2 xml:id="language.types.relative-class-types.parent">
+ <title><type>parent</type></title>
+ <para>
+ The value must be an &instanceof; a parent of the class
+ in which the type declaration is used.
+ </para>
+ </sect2>
+
+ <sect2 xml:id="language.types.relative-class-types.static">
+ <title>static</title>
+ <para>
+ <type>static</type> is a return-only type which requires that the
+ value returned must be an &instanceof; the same class as the one
+ the method is called in.
+ Available as of PHP 8.0.0.
+ </para>
+ </sect2>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
diff --git a/language/types/string.xml b/language/types/string.xml
index 64f5ce70bef..139c4233a03 100644
--- a/language/types/string.xml
+++ b/language/types/string.xml
@@ -1308,15 +1308,7 @@ bool(false)
<listitem>
<simpara>
Others use the current locale (see <function>setlocale</function>), but
- operate byte-by-byte. This is the case of <function>strcasecmp</function>,
- <function>strtoupper</function> and <function>ucfirst</function>.
- This means they can be used only with single-byte encodings, as long as
- the encoding is matched by the locale. For instance
- <literal>strtoupper("á")</literal> may return <literal>"Á"</literal> if the
- locale is correctly set and <literal>á</literal> is encoded with a single
- byte. If it is encoded in UTF-8, the correct result will not be returned
- and the resulting string may or may not be returned corrupted, depending
- on the current locale.
+ operate byte-by-byte.
</simpara>
</listitem>
<listitem>
@@ -1326,9 +1318,6 @@ bool(false)
<link linkend="book.intl">intl</link> extension and in the
<link linkend="book.pcre">PCRE</link> extension
(in the last case, only when the <literal>u</literal> modifier is used).
- Although this is due to their special purpose, the function
- <function>utf8_decode</function> assumes a UTF-8 encoding and the
- function <function>utf8_encode</function> assumes an ISO-8859-1 encoding.
</simpara>
</listitem>
</itemizedlist>
diff --git a/language/types/type-juggling.xml b/language/types/type-juggling.xml
index f27d3361118..f3dacf08c7a 100644
--- a/language/types/type-juggling.xml
+++ b/language/types/type-juggling.xml
@@ -81,6 +81,8 @@
<simpara>
In this context the value will be interpreted as <type>string</type>.
+ If the value cannot be interpreted a <classname>TypeError</classname> is thrown.
+ Prior to PHP 7.4.0, an <constant>E_RECOVERABLE_ERROR</constant> was raised.
</simpara>
</sect2>
@@ -131,7 +133,7 @@
</simpara>
</sect2>
- <sect2>
+ <sect2 xml:id="language.types.type-juggling.function">
<title>Function contexts</title>
<simpara>
@@ -140,9 +142,26 @@
</simpara>
<para>
- In this context, when coercive typing mode is active (the default),
- only scalar values may be converted to another scalar value.
- For simple types declarations the behaviour is as follows:
+ In this context the value must be a value of the type.
+ Two exceptions exist, the first one is: if the value is of type
+ <type>int</type> and the declared type is <type>float</type>, then the
+ integer is converted to a floating point number.
+ The second one is: if the value and the declared type are
+ <emphasis>scalar</emphasis> types, and the coercive typing mode is active
+ (the default), the value may be converted to an accepted scalar valued.
+ See below for a description of this behaviour.
+ </para>
+
+ <warning>
+ <simpara>
+ <link linkend="functions.internal">Internal functions</link>
+ automatically coerce &null; to scalar types,
+ this behaviour is <emphasis>DEPRECATED</emphasis> as of PHP 8.1.0.
+ </simpara>
+ </warning>
+
+ <sect3 xml:id="language.types.type-juggling.function.simple">
+ <title>Coercive typing with simple type declarations</title>
<itemizedlist>
<listitem>
<simpara>
@@ -169,18 +188,91 @@
</simpara>
</listitem>
</itemizedlist>
+ </sect3>
- If the type declaration is a union, see the section about
- <link linkend="language.types.declarations.union.coercive">Coercive typing with \
union types</link>.
- </para>
+ <sect3 xml:id="language.types.type-juggling.function.union">
+ <title>Coercive typing with union types</title>
+ <para>
+ When <literal>strict_types</literal> is not enabled, scalar type declarations
+ are subject to limited implicit type coercions.
+ If the exact type of the value is not part of the union, then the target type
+ is chosen in the following order of preference:
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ <type>int</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>float</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>string</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>bool</type>
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ If the type both exists in the union, and the value can be coerced to the
+ type under PHPs existing type checking semantics, then the type is chosen.
+ Otherwise, the next type is tried.
+ </para>
+
+ <caution>
+ <para>
+ As an exception, if the value is a string and both int and float are part
+ of the union, the preferred type is determined by the existing
+ "numeric string" semantics.
+ For example, for <literal>"42"</literal> <type>int</type> is chosen,
+ while for <literal>"42.0"</literal> <type>float</type> is chosen.
+ </para>
+ </caution>
+
+ <note>
+ <para>
+ Types that are not part of the above preference list are not eligible
+ targets for implicit coercion. In particular no implicit coercions to
+ the <literal>null</literal> and <literal>false</literal> types occur.
+ </para>
+ </note>
+
+ <example>
+ <title>Example of types being coerced into a type part of the union</title>
+ <programlisting>
+<![CDATA[
+// int|string
+42 --> 42 // exact type
+"42" --> "42" // exact type
+new ObjectWithToString --> "Result of __toString()"
+ // object never compatible with int, fall back to string
+42.0 --> 42 // float compatible with int
+42.1 --> 42 // float compatible with int
+1e100 --> "1.0E+100" // float too large for int type, fall back to string
+INF --> "INF" // float too large for int type, fall back to string
+true --> 1 // bool compatible with int
+[] --> TypeError // array not compatible with int or string
+
+// int|float|bool
+"45" --> 45 // int numeric string
+"45.0" --> 45.0 // float numeric string
+
+"45X" --> true // not numeric string, fall back to bool
+"" --> false // not numeric string, fall back to bool
+"X" --> true // not numeric string, fall back to bool
+[] --> TypeError // array not compatible with int, float or bool
+]]>
+ </programlisting>
+ </example>
+ </sect3>
- <warning>
- <simpara>
- <link linkend="functions.internal">Internal functions</link>
- automatically coerce &null; to scalar types,
- this behaviour is <emphasis>DEPRECATED</emphasis> as of PHP 8.1.0.
- </simpara>
- </warning>
</sect2>
<sect2 xml:id="language.types.typecasting">
diff --git a/language/types/type-system.xml b/language/types/type-system.xml
new file mode 100644
index 00000000000..217c9052c2e
--- /dev/null
+++ b/language/types/type-system.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.type-system">
+ <title>Type System</title>
+
+ <para>
+ PHP uses a nominal type system with a strong behavioral subtyping relation.
+ The subtyping relation is checked at compile time whereas the verification of
+ types is dynamically checked at run time.
+ </para>
+
+ <para>
+ PHP's type system supports various base types that can be composed together
+ to create more complex types. Some of these types can be written as
+ <link linkend="language.types.declarations">type declarations</link>.
+ </para>
+
+ <sect2 xml:id="language.types.type-system.base">
+ <title>Base types</title>
+ <para>
+ Some base types are built-in types which are tightly integrated with the
+ language and cannot be reproduced with user defined types.
+ </para>
+
+ <para>
+ The list of base types is:
+ <itemizedlist>
+ <listitem>
+ <simpara>Built-in types</simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara><type>null</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Scalar types:
+ </simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara><type>bool</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>int</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>float</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>float</type> string</simpara>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <simpara><type>array</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>object</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>resource</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>never</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>void</type> type</simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <link linkend="language.types.relative-class-types">Relative class \
types</link>: + <type>self</type>, <type>parent</type>, and \
<type>static</type> + </simpara>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <simpara>
+ <link linkend="language.types.literal">Literal types</link>
+ </simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara><type>false</type></simpara>
+ </listitem>
+ <listitem>
+ <simpara><type>true</type></simpara>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <simpara>
+ User-defined types (generally referred to as class-types)
+ </simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara><link linkend="language.oop5.interfaces">Interfaces</link></simpara>
+ </listitem>
+ <listitem>
+ <simpara><link linkend="language.oop5.basic.class">Classes</link></simpara>
+ </listitem>
+ <listitem>
+ <simpara><link \
linkend="language.types.enumerations">Enumerations</link></simpara> + \
</listitem> + </itemizedlist>
+ </listitem>
+ <listitem>
+ <simpara><type>callable</type> type</simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+
+ <sect2 xml:id="language.types.type-system.composite">
+ <title>Composite types</title>
+ <para>
+ It is possible to combine simple types into composite types.
+ PHP allows types to be combined in the following ways:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Intersection of class-types (interfaces and class names).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Union of types.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <sect3 xml:id="language.types.type-system.composite.intersection">
+ <title>Intersection types</title>
+ <para>
+ An intersection type accepts values which satisfies multiple
+ class-type declarations, rather than a single one.
+ Individual types which form the intersection type are joined by the
+ <literal>&</literal> symbol. Therefore, an intersection type comprised
+ of the types <literal>T</literal>, <literal>U</literal>, and
+ <literal>V</literal> will be written as <literal>T&U&V</literal>.
+ </para>
+ </sect3>
+
+ <sect3 xml:id="language.types.type-system.composite.union">
+ <title>Union types</title>
+ <para>
+ A union type accepts values of multiple different types,
+ rather than a single one.
+ Individual types which form the union type are joined by the
+ <literal>|</literal> symbol. Therefore, a union type comprised
+ of the types <literal>T</literal>, <literal>U</literal>, and
+ <literal>V</literal> will be written as <literal>T|U|V</literal>.
+ If one of the types is an intersection type, it needs to be bracketed
+ with parenthesis for it to written in <acronym>DNF</acronym>:
+ <literal>T|(X&Y)</literal>.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="language.types.type-system.alias">
+ <title>Type aliases</title>
+
+ <para>
+ PHP supports a two type aliases: <type>mixed</type> and
+ <type>iterable</type> which corresponds to the
+ <link linkend="language.types.type-system.composite.union">union type</link>
+ of <literal>object|resource|array|string|float|int|bool|null</literal>
+ and <literal>Traversable|array</literal> respectively.
+ </para>
+
+ <note>
+ <simpara>
+ PHP does not support user-defined type aliases.
+ </simpara>
+ </note>
+ </sect2>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
diff --git a/language/types/void.xml b/language/types/void.xml
new file mode 100644
index 00000000000..9b8e3af05fe
--- /dev/null
+++ b/language/types/void.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sect1 xml:id="language.types.void">
+ <title>Void</title>
+
+ <para>
+ <type>void</type> is a return-only type declaration indicating the
+ function does not return a value, but the function may still terminate.
+ Therefore, it cannot be part of a
+ <link linkend="language.types.type-system.composite.union">union type</link>
+ declaration. Available as of PHP 7.1.0.
+ </para>
+
+ <note>
+ <simpara>
+ Even if a function has a return type of <type>void</type> it will
+ still return a value, this value is always &null;.
+ </simpara>
+ </note>
+
+</sect1>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
--
PHP Documentation Commits Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic