1--TEST-- 2Union of null and intersection type 3--FILE-- 4<?php 5 6interface X {} 7interface Y {} 8 9class A implements X, Y {} 10class C {} 11 12class Test { 13 public (X&Y)|null $prop1; 14 public null|(X&Y) $prop2; 15 16 public function foo1((X&Y)|null $v): (X&Y)|null { 17 var_dump($v); 18 return $v; 19 } 20 public function foo2(null|(X&Y) $v): null|(X&Y) { 21 var_dump($v); 22 return $v; 23 } 24} 25 26$test = new Test(); 27$a = new A(); 28$n = null; 29 30$test->foo1($a); 31$test->foo2($a); 32$test->foo1($n); 33$test->foo2($n); 34$test->prop1 = $a; 35$test->prop1 = $n; 36$test->prop2 = $a; 37$test->prop2 = $n; 38 39$c = new C(); 40try { 41 $test->foo1($c); 42} catch (\TypeError $e) { 43 echo $e->getMessage(), \PHP_EOL; 44} 45try { 46 $test->foo2($c); 47} catch (\TypeError $e) { 48 echo $e->getMessage(), \PHP_EOL; 49} 50try { 51 $test->prop1 = $c; 52} catch (\TypeError $e) { 53 echo $e->getMessage(), \PHP_EOL; 54} 55try { 56 $test->prop2 = $c; 57} catch (\TypeError $e) { 58 echo $e->getMessage(), \PHP_EOL; 59} 60 61?> 62===DONE=== 63--EXPECTF-- 64object(A)#2 (0) { 65} 66object(A)#2 (0) { 67} 68NULL 69NULL 70Test::foo1(): Argument #1 ($v) must be of type (X&Y)|null, C given, called in %s on line %d 71Test::foo2(): Argument #1 ($v) must be of type (X&Y)|null, C given, called in %s on line %d 72Cannot assign C to property Test::$prop1 of type (X&Y)|null 73Cannot assign C to property Test::$prop2 of type (X&Y)|null 74===DONE=== 75