[presentations] master: Tweaks

[email protected] (Rasmus Lerdorf) Wed, 29 Sep 2021 17:52:14 +0000
Newsgroups php.pres
Message-ID <[email protected]>
Author: Rasmus Lerdorf (rlerdorf)
Date: 2021-09-29T10:52:41-07:00

Commit: https://github.com/php/presentations/commit/306f90b64a8b9b8948c80d0f4bbd2f39a7476a13
Raw diff: https://github.com/php/presentations/commit/306f90b64a8b9b8948c80d0f4bbd2f39a7476a13.diff

Tweaks

Changed paths:
  A  slides/intro/php81_2021.xml
  M  etsymex21.html
  M  etsymex21.xml


Diff:

diff --git a/etsymex21.html b/etsymex21.html
index ea61c7c9..251add2a 100644
--- a/etsymex21.html
+++ b/etsymex21.html
@@ -201,7 +201,7 @@ <h3>Sep.30, 2021</h3>
 		</section>
 		<section id="etsyfw2" >
 		<p class="p" style="font-size:1.4em;text-align:left;">awesome.php</p>
-		<pre><code data-trim style="font-size:1em;" >require 'bootstrap.php';
+		<pre><code data-trim style="font-size:1em;" >require &#039;bootstrap.php&#039;;
 $request  = HTTP_Request::getInstance();
 $response = HTTP_Response::getInstance();
 $controller = new Awesome_Controller();
@@ -214,13 +214,13 @@ <h3>Sep.30, 2021</h3>
 		<p class="p" style="font-size:1.4em;text-align:left;">Code/Awesome/Controller.php</p>
 		<pre><code data-trim style="font-size:1em;" >class Awesome_Controller extends Controller_Base {
   public function doCoolThings($request, $response) {
-    $id = $request-&gt;getGet('id', 0);
+    $id = $request-&gt;getGet(&#039;id&#039;, 0);
     if (!$id) {
       $response-&gt;redirect_error(Constants::ERROR_NOT_FOUND);
       return;
     }
-    $thing = EtsyORM::getFinder('Thing')-&gt;findById($id);
-    $stuff = Api::endpoint('AwesomeStuff', [$thing-&gt;id, 'max'=&gt;10]);
+    $thing = EtsyORM::getFinder(&#039;Thing&#039;)-&gt;findById($id);
+    $stuff = Api::endpoint(&#039;AwesomeStuff&#039;, [$thing-&gt;id, &#039;max&#039;=&gt;10]);
     $this-&gt;renderViewTree(New Awesome_View($thing, $stuff));
   }
 }</code></pre>
@@ -240,12 +240,12 @@ <h3>Sep.30, 2021</h3>
         $this-&gt;stuff = $stuff;
     }
     public function getCssFiles(): array {
-        return [ '/awesome/main.scss' ];
+        return [ &#039;/awesome/main.scss&#039; ];
     }
     public function getTemplateData(): array {
-        return [ 'thing_id' =&gt; $this-&gt;thing-&gt;id,
-                 'thing_name' =&gt; $this-&gt;thing-&gt;name,
-                 'stuff' =&gt; $this-&gt;stuff ];
+        return [ &#039;thing_id&#039; =&gt; $this-&gt;thing-&gt;id,
+                 &#039;thing_name&#039; =&gt; $this-&gt;thing-&gt;name,
+                 &#039;stuff&#039; =&gt; $this-&gt;stuff ];
     }
 }</code></pre>
 		</section>
@@ -272,9 +272,9 @@ <h1 style="text-align:center;">Static Analysis</h1>
 		<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ composer require --dev phan/phan</code></pre>
 		<p class="p" style="font-size:1.5em;text-align:left;">Create .phan/config.php</p>
 		<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >return [
-    'target_php_version' =&gt; '8.0',
-    'directory_list' =&gt; [ 'src/' ],
-    &quot;exclude_analysis_directory_list&quot; =&gt; [ 'vendor/' ],
+    &#039;target_php_version&#039; =&gt; &#039;8.0&#039;,
+    &#039;directory_list&#039; =&gt; [ &#039;src/&#039; ],
+    &quot;exclude_analysis_directory_list&quot; =&gt; [ &#039;vendor/&#039; ],
 ];</code></pre>
 		<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ ./vendor/bin/phan</code></pre>
 		</section>
@@ -294,7 +294,7 @@ <h1 style="text-align:center;">Static Analysis</h1>
 		<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ phan --daemonize-tcp-port default &amp;
 [1] 28610
 Listening for Phan analysis requests at tcp://127.0.0.1:4846
-Awaiting analysis requests for directory '/home/rasmus/phan_demo'
+Awaiting analysis requests for directory &#039;/home/rasmus/phan_demo&#039;
 
 $ vi src/script.php</code></pre>
 		<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ phan_client -l src/script.php
@@ -322,7 +322,7 @@ <h1 style="text-align:center;">phpspy</h1>
 		</section>
 		<section id="spy1" >
 		<p class="p" style="font-size:1.1em;text-align:left;">Sample frequency in nanoseconds (or Hz)</p>
-		<pre><code class="shell nohighlight" data-trim style="font-size:0.9em;" >$ phpspy -s 200000000 -- php -r 'sleep(1);' 
+		<pre><code class="shell nohighlight" data-trim style="font-size:0.9em;" >$ phpspy -s 200000000 -- php -r &#039;sleep(1);&#039; 
 0 sleep &lt;internal&gt;:-1
 1 &lt;main&gt; &lt;internal&gt;:-1
 
@@ -482,7 +482,7 @@ <h2 style="text-align:center;">How do you manage deploys?</h2>
 *** pushbot has changed the topic on #push to &lt;prod&gt; *joe *frank|bob Rasmus
 joe: .done
 *** pushbot has changed the topic on #push to &lt;prod&gt; bob Rasmus
-pushbot: bob Rasmus: You're up
+pushbot: bob Rasmus: You&#039;re up
 bob: .in
 *** pushbot has changed the topic on #push *bob Rasmus
 Rasmus: .in
@@ -618,7 +618,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
 
 // instead of
 
-htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);</code></pre>
+htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, &#039;UTF-8&#039;, false);</code></pre>
 		</section>
 		<section id="php80_promotion" >
 		<p class="p" style="font-size:1.1em;text-align:left;">Constructor Property Promotion</p>
@@ -655,16 +655,16 @@ <h1 style="text-align:center;">PHP 8.0</h1>
 		</section>
 		<section id="php80_match" >
 		<p class="p" style="font-size:1em;text-align:left;">Match Expression</p>
-		<pre><code data-trim style="font-size:0.9em;" >$statement = match ($this-&gt;lexer-&gt;lookahead['type']) {
+		<pre><code data-trim style="font-size:0.9em;" >$statement = match ($this-&gt;lexer-&gt;lookahead[&#039;type&#039;]) {
     Lexer::T_SELECT =&gt; $this-&gt;SelectStatement(),
     Lexer::T_UPDATE =&gt; $this-&gt;UpdateStatement(),
     Lexer::T_DELETE =&gt; $this-&gt;DeleteStatement(),
-    default =&gt; $this-&gt;syntaxError('SELECT, UPDATE or DELETE'),
+    default =&gt; $this-&gt;syntaxError(&#039;SELECT, UPDATE or DELETE&#039;),
 };
 // Throws UnhandledMatchError on no match and no default expr
 
 // instead of
-switch ($this-&gt;lexer-&gt;lookahead['type']) {
+switch ($this-&gt;lexer-&gt;lookahead[&#039;type&#039;]) {
     case Lexer::T_SELECT:
         $statement = $this-&gt;SelectStatement();
         break;
@@ -675,7 +675,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
         $statement = $this-&gt;DeleteStatement();
         break;
     default:
-        $this-&gt;syntaxError('SELECT, UPDATE or DELETE');
+        $this-&gt;syntaxError(&#039;SELECT, UPDATE or DELETE&#039;);
         break;
 }</code></pre>
 <aside class="notes"><br />
@@ -725,7 +725,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
         return self::$data[$key];
     }
 }
-Store::add('player2', [1,2,3]);
+Store::add(&#039;player2&#039;, [1,2,3]);
 // TypeError: Store::add(): Argument #2 ($val) must be of
 //                          type string|int|float, array given</code></pre>
 <aside class="notes"><br />
@@ -752,14 +752,14 @@ <h1 style="text-align:center;">PHP 8.0</h1>
 }
 
 $xkcd = new Endpoint(&quot;http://xkcd.com/info.0.json&quot;, fn($x)=&gt;json_decode($x, associative:false));
-$joke = new Endpoint(&quot;https://icanhazdadjoke.com/&quot;, opts:['http'=&gt;['header'=&gt;&quot;Accept:text/plain&quot;]]);
-echo '&lt;img src=&quot;'.Api::fetch($xkcd)-&gt;img.'&quot; alt=&quot;'.Api::fetch($xkcd)-&gt;alt.'&quot;&gt;'.&quot;\n&quot;;
+$joke = new Endpoint(&quot;https://icanhazdadjoke.com/&quot;, opts:[&#039;http&#039;=&gt;[&#039;header&#039;=&gt;&quot;Accept:text/plain&quot;]]);
+echo &#039;&lt;img src=&quot;&#039;.Api::fetch($xkcd)-&gt;img.&#039;&quot; alt=&quot;&#039;.Api::fetch($xkcd)-&gt;alt.&#039;&quot;&gt;&#039;.&quot;\n&quot;;
 echo Api::fetch($joke) . &quot;\n&quot;;
 echo Api::$cache-&gt;count() . &quot;\n&quot;; // 2
 unset($xkcd);
 echo Api::$cache-&gt;count() . &quot;\n&quot;; // 1
 echo Api::fetch($joke) . &quot;\n&quot;;    // Same bad joke
-$joke = new Endpoint(&quot;https://icanhazdadjoke.com/&quot;, opts:['http'=&gt;['header'=&gt;&quot;Accept:text/plain&quot;]]);
+$joke = new Endpoint(&quot;https://icanhazdadjoke.com/&quot;, opts:[&#039;http&#039;=&gt;[&#039;header&#039;=&gt;&quot;Accept:text/plain&quot;]]);
 echo Api::fetch($joke) . &quot;\n&quot;;    // New bad joke
 echo Api::$cache-&gt;count() . &quot;\n&quot;; // 2?
 gc_collect_cycles();              // Force gc
@@ -779,7 +779,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
     private $id;
 
     #[ORM\Column(&quot;string&quot;, ORM\Column::UNIQUE)]
-    #[Assert\Email(array(&quot;message&quot; =&gt; &quot;The email '{{ value }}' is not a valid email.&quot;))]
+    #[Assert\Email(array(&quot;message&quot; =&gt; &quot;The email &#039;{{ value }}&#039; is not a valid email.&quot;))]
     private $email;
 
     #[Assert\Range([&quot;min&quot; =&gt; 120, &quot;max&quot; =&gt; 180, &quot;minMessage&quot; =&gt; &quot;You must be at least {{ limit }}cm tall to enter&quot;])]
@@ -798,6 +798,142 @@ <h1 style="text-align:center;">PHP 8.0</h1>
 One per line, or comma-separated on same attribute line<br />
 </aside>
 		</section>	</section>
+	<section>
+		<section id="php81">
+		<h1 style="text-align:center;">PHP 8.1</h1>
+		</section>
+		<section id="php81_readonly_props" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Readonly properties</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/readonly_properties_v2" target="">https://wiki.php.net/rfc/readonly_properties_v2</a></div>
+		<pre><code data-trim style="font-size:1em;" >class Test {
+  public readonly string $prop;
+
+  public function __construct(string $prop) {
+    $this-&gt;prop = $prop; // Initialized once in same scope
+  }
+}
+
+$test = new Test(&quot;foobar&quot;);
+var_dump($test-&gt;prop);
+$test-&gt;prop = &quot;foobar&quot;; // Error</code></pre>
+		</section>
+		<section id="php81_enums" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Enums</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/enumerations" target="">https://wiki.php.net/rfc/enumerations</a></div>
+		<pre><code data-trim style="font-size:1em;" >enum Suit {
+  case Hearts;
+  case Diamonds;
+  case Clubs;
+  case Spades;
+}
+
+function pick_a_card(Suit $suit) { ... }
+pick_a_card(Suit::Clubs); // ok
+pick_a_card(&#039;Spades&#039;);    // error</code></pre>
+		</section>
+		<section id="php81_fibers" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Fibers</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/fibers" target="">https://wiki.php.net/rfc/fibers</a></div>
+		<pre><code data-trim style="font-size:1em;" >use React\EventLoop\LoopInterface;
+use React\Promise\PromiseInterface;
+
+function await(PromiseInterface $promise, LoopInterface $loop): mixed {
+  $fiber = Fiber::this();
+  $promise-&gt;done(
+    fn(mixed $value) =&gt; $loop-&gt;futureTick(fn() =&gt; $fiber-&gt;resume($value)),
+    fn(Throwable $reason) =&gt; $loop-&gt;futureTick(fn() =&gt; $fiber-&gt;throw($reason))
+  );
+
+  return Fiber::suspend();
+}</code></pre>
+		</section>
+		<section id="php81_fibers" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Static Variable Inheritance</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/static_variable_inheritance" target="">https://wiki.php.net/rfc/static_variable_inheritance</a></div>
+		<pre><code data-trim style="font-size:1em;" >class A {
+  public static function counter() {
+    static $i = 0;
+    return ++$i;
+  }
+}
+class B extends A {}
+
+echo A::counter();
+echo A::counter();
+echo B::counter();
+echo B::counter();
+// PHP 8.0 outputs 1212
+// PHP 8.1 outputs 1234</code></pre>
+		</section>
+		<section id="php81_never" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Never Return Type</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/noreturn_type" target="">https://wiki.php.net/rfc/noreturn_type</a></div>
+		<pre><code data-trim style="font-size:1em;" >function redirect(string $uri): never {
+  header(&#039;Location: &#039; . $uri);
+  exit();
+}
+
+redirect(&#039;/index.html&#039;);
+echo &quot;this will never be executed!&quot;;</code></pre>
+		</section>
+		<section id="php81_final" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Final class constants</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/final_class_const" target="">https://wiki.php.net/rfc/final_class_const</a></div>
+		<pre><code data-trim style="font-size:1em;" >class Foo {
+    final public const X = &quot;foo&quot;;
+}
+
+class Bar extends Foo {
+    public const X = &quot;bar&quot;;
+}
+
+// Fatal error: Bar::X cannot override final constant Foo::X</code></pre>
+		</section>
+		<section id="php81_new_init" >
+		<p class="p" style="font-size:1.1em;text-align:left;">New in initializers</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/new_in_initializers" target="">https://wiki.php.net/rfc/new_in_initializers</a></div>
+		<pre><code data-trim style="font-size:1em;" >class Test {
+  public function __construct(private Logger $logger = new NullLogger) {}
+}
+
+// instead of
+
+class Test {
+  private Logger $logger;
+
+  public function __construct(?Logger $logger = null) {
+        $this-&gt;logger = $logger ?? new NullLogger;
+    }
+}</code></pre>
+		</section>
+		<section id="php81_first_class_callable" >
+		<p class="p" style="font-size:1.1em;text-align:left;">First-class callable syntax</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/first_class_callable_syntax" target="">https://wiki.php.net/rfc/first_class_callable_syntax</a></div>
+		<pre><code data-trim style="font-size:1em;" >$fn = strlen(...);
+$fn = $this-&gt;method(...)
+$fn = Foo::method(...);
+
+// instead of
+
+$fn = Closure::fromCallable(&#039;strlen&#039;);
+$fn = Closure::fromCallable([$this, &#039;method&#039;]);
+$fn = Closure::fromCallable([Foo::class, &#039;method&#039;]);</code></pre>
+		</section>
+		<section id="php81_pure_intersection" >
+		<p class="p" style="font-size:1.1em;text-align:left;">Pure intersection types</p>
+		<div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/pure-intersection-types" target="">https://wiki.php.net/rfc/pure-intersection-types</a></div>
+		<pre><code data-trim style="font-size:1em;" >class A {
+  private Traversable&amp;Countable $countableIterator;
+
+  public function setIterator(Traversable&amp;Countable $countableIterator): void {
+    $this-&gt;countableIterator = $countableIterator;
+  }
+
+  public function getIterator(): Traversable&amp;Countable {
+    return $this-&gt;countableIterator;
+  }
+}</code></pre>
+		</section>	</section>
 	<section data-background-color="#000000">
 		<section id="j">
 		<img src="/presentations/slides/intro/carl1.jpg" align="center" width="533" height="800">
diff --git a/etsymex21.xml b/etsymex21.xml
index 6b69e560..37af11bf 100644
--- a/etsymex21.xml
+++ b/etsymex21.xml
@@ -34,6 +34,7 @@
 <slide>slides/intro/wp2021.xml</slide>
 <slide>slides/intro/storage.xml</slide>
 <slide>slides/intro/php80_2021.xml</slide>
+<slide>slides/intro/php81_2021.xml</slide>
 <slide>slides/intro/journey_etsy.xml</slide>
 <slide>slides/intro/matter_etsy.xml</slide>
 <slide>slides/intro/sahana.xml</slide>
diff --git a/slides/intro/php81_2021.xml b/slides/intro/php81_2021.xml
new file mode 100644
index 00000000..ce5eda24
--- /dev/null
+++ b/slides/intro/php81_2021.xml
@@ -0,0 +1,156 @@
+<slide title="" section="php81">
+
+<blurb fontsize="20em" align="center">PHP 8.1</blurb>
+
+<break lines="1" section="php81_readonly_props"/>
+<blurb fontsize="1.1em" align="left">Readonly properties</blurb>
+<link align="left" href="https://wiki.php.net/rfc/readonly_properties_v2"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Test {
+  public readonly string $prop;
+
+  public function __construct(string $prop) {
+    $this->prop = $prop; // Initialized once in same scope
+  }
+}
+
+$test = new Test("foobar");
+var_dump($test->prop);
+$test->prop = "foobar"; // Error
+]]></example>
+
+<break lines="1" section="php81_enums"/>
+<blurb fontsize="1.1em" align="left">Enums</blurb>
+<link align="left"  href="https://wiki.php.net/rfc/enumerations"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+enum Suit {
+  case Hearts;
+  case Diamonds;
+  case Clubs;
+  case Spades;
+}
+
+function pick_a_card(Suit $suit) { ... }
+pick_a_card(Suit::Clubs); // ok
+pick_a_card('Spades');    // error
+]]></example>
+
+<break lines="1" section="php81_fibers"/>
+<blurb fontsize="1.1em" align="left">Fibers</blurb>
+<link align="left" href="https://wiki.php.net/rfc/fibers"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+use React\EventLoop\LoopInterface;
+use React\Promise\PromiseInterface;
+
+function await(PromiseInterface $promise, LoopInterface $loop): mixed {
+  $fiber = Fiber::this();
+  $promise->done(
+    fn(mixed $value) => $loop->futureTick(fn() => $fiber->resume($value)),
+    fn(Throwable $reason) => $loop->futureTick(fn() => $fiber->throw($reason))
+  );
+
+  return Fiber::suspend();
+}
+]]></example>
+
+<break lines="1" section="php81_fibers"/>
+<blurb fontsize="1.1em" align="left">Static Variable Inheritance</blurb>
+<link align="left" href="https://wiki.php.net/rfc/static_variable_inheritance"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class A {
+  public static function counter() {
+    static $i = 0;
+    return ++$i;
+  }
+}
+class B extends A {}
+
+echo A::counter();
+echo A::counter();
+echo B::counter();
+echo B::counter();
+// PHP 8.0 outputs 1212
+// PHP 8.1 outputs 1234
+]]></example>
+
+<break lines="1" section="php81_never"/>
+<blurb fontsize="1.1em" align="left">Never Return Type</blurb>
+<link align="left" href="https://wiki.php.net/rfc/noreturn_type"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+function redirect(string $uri): never {
+  header('Location: ' . $uri);
+  exit();
+}
+
+redirect('/index.html');
+echo "this will never be executed!";
+]]></example>
+
+<break lines="1" section="php81_final"/>
+<blurb fontsize="1.1em" align="left">Final class constants</blurb>
+<link align="left" href="https://wiki.php.net/rfc/final_class_const"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Foo {
+    final public const X = "foo";
+}
+
+class Bar extends Foo {
+    public const X = "bar";
+}
+
+// Fatal error: Bar::X cannot override final constant Foo::X
+]]></example>
+
+<break lines="1" section="php81_new_init"/>
+<blurb fontsize="1.1em" align="left">New in initializers</blurb>
+<link align="left" href="https://wiki.php.net/rfc/new_in_initializers"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Test {
+  public function __construct(private Logger $logger = new NullLogger) {}
+}
+
+// instead of
+
+class Test {
+  private Logger $logger;
+
+  public function __construct(?Logger $logger = null) {
+        $this->logger = $logger ?? new NullLogger;
+    }
+}
+]]></example>
+
+<break lines="1" section="php81_first_class_callable"/>
+<blurb fontsize="1.1em" align="left">First-class callable syntax</blurb>
+<link align="left" href="https://wiki.php.net/rfc/first_class_callable_syntax"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+$fn = strlen(...);
+$fn = $this->method(...)
+$fn = Foo::method(...);
+
+// instead of
+
+$fn = Closure::fromCallable('strlen');
+$fn = Closure::fromCallable([$this, 'method']);
+$fn = Closure::fromCallable([Foo::class, 'method']);
+]]></example>
+
+<break lines="1" section="php81_pure_intersection"/>
+<blurb fontsize="1.1em" align="left">Pure intersection types</blurb>
+<link align="left" href="https://wiki.php.net/rfc/pure-intersection-types"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class A {
+  private Traversable&Countable $countableIterator;
+
+  public function setIterator(Traversable&Countable $countableIterator): void {
+    $this->countableIterator = $countableIterator;
+  }
+
+  public function getIterator(): Traversable&Countable {
+    return $this->countableIterator;
+  }
+}
+]]></example>
+
+
+</slide>