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