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