1--TEST-- 2Union of a simple and intersection type 3--FILE-- 4<?php 5 6interface X {} 7interface Y {} 8 9class A implements X, Y {} 10class B {} 11class C {} 12 13class Test { 14 public (X&Y)|int $prop1; 15 public int|(X&Y) $prop2; 16 public (X&Y)|B $prop3; 17 public B|(X&Y) $prop4; 18 19 public function foo1((X&Y)|int $v): (X&Y)|int { 20 var_dump($v); 21 return $v; 22 } 23 public function foo2(int|(X&Y) $v): int|(X&Y) { 24 var_dump($v); 25 return $v; 26 } 27 public function bar1(B|(X&Y) $v): B|(X&Y) { 28 var_dump($v); 29 return $v; 30 } 31 public function bar2((X&Y)|B $v): (X&Y)|B { 32 var_dump($v); 33 return $v; 34 } 35} 36 37$test = new Test(); 38$a = new A(); 39$b = new B(); 40$i = 10; 41 42$test->foo1($a); 43$test->foo2($a); 44$test->foo1($i); 45$test->foo2($i); 46$test->prop1 = $a; 47$test->prop1 = $i; 48$test->prop2 = $a; 49$test->prop2 = $i; 50 51$test->bar1($a); 52$test->bar2($a); 53$test->bar1($b); 54$test->bar2($b); 55$test->prop3 = $a; 56$test->prop4 = $b; 57$test->prop3 = $a; 58$test->prop4 = $b; 59 60$c = new C(); 61try { 62 $test->foo1($c); 63} catch (\TypeError $e) { 64 echo $e->getMessage(), \PHP_EOL; 65} 66try { 67 $test->foo2($c); 68} catch (\TypeError $e) { 69 echo $e->getMessage(), \PHP_EOL; 70} 71try { 72 $test->bar1($c); 73} catch (\TypeError $e) { 74 echo $e->getMessage(), \PHP_EOL; 75} 76try { 77 $test->bar2($c); 78} catch (\TypeError $e) { 79 echo $e->getMessage(), \PHP_EOL; 80} 81try { 82 $test->prop1 = $c; 83} catch (\TypeError $e) { 84 echo $e->getMessage(), \PHP_EOL; 85} 86try { 87 $test->prop2 = $c; 88} catch (\TypeError $e) { 89 echo $e->getMessage(), \PHP_EOL; 90} 91try { 92 $test->prop3 = $c; 93} catch (\TypeError $e) { 94 echo $e->getMessage(), \PHP_EOL; 95} 96try { 97 $test->prop4 = $c; 98} catch (\TypeError $e) { 99 echo $e->getMessage(), \PHP_EOL; 100} 101 102?> 103===DONE=== 104--EXPECTF-- 105object(A)#2 (0) { 106} 107object(A)#2 (0) { 108} 109int(10) 110int(10) 111object(A)#2 (0) { 112} 113object(A)#2 (0) { 114} 115object(B)#3 (0) { 116} 117object(B)#3 (0) { 118} 119Test::foo1(): Argument #1 ($v) must be of type (X&Y)|int, C given, called in %s on line %d 120Test::foo2(): Argument #1 ($v) must be of type (X&Y)|int, C given, called in %s on line %d 121Test::bar1(): Argument #1 ($v) must be of type B|(X&Y), C given, called in %s on line %d 122Test::bar2(): Argument #1 ($v) must be of type (X&Y)|B, C given, called in %s on line %d 123Cannot assign C to property Test::$prop1 of type (X&Y)|int 124Cannot assign C to property Test::$prop2 of type (X&Y)|int 125Cannot assign C to property Test::$prop3 of type (X&Y)|B 126Cannot assign C to property Test::$prop4 of type B|(X&Y) 127===DONE=== 128