[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&amp;T2&amp;...</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 @@
   &#8484; = {..., -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>&amp;</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&amp;U&amp;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&amp;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