1--TEST--
2GH-9516: (A&B)|D as a param should allow AB or D. Not just A.
3--FILE--
4<?php
5
6interface A { }
7interface B { }
8interface D { }
9
10class A_ implements A {}
11class B_ implements B {}
12class AB_ implements A, B {}
13class D_ implements D {}
14
15class T {
16    public function method1((A&B)|D $arg): void {}
17    public function method2((B&A)|D $arg): void {}
18    public function method3(D|(A&B) $arg): void {}
19    public function method4(D|(B&A) $arg): void {}
20}
21
22$t = new T;
23
24try {
25    $t->method1(new A_);
26    echo 'Fail', \PHP_EOL;
27} catch (\Throwable $throwable) {
28    echo $throwable->getMessage(), \PHP_EOL;
29}
30
31try {
32    $t->method1(new B_);
33    echo 'Fail', \PHP_EOL;
34} catch (\Throwable $throwable) {
35    echo $throwable->getMessage(), \PHP_EOL;
36}
37
38try {
39    $t->method1(new AB_);
40    echo 'Pass', \PHP_EOL;
41} catch (\Throwable $throwable) {
42    echo $throwable->getMessage(), \PHP_EOL;
43}
44
45try {
46    $t->method1(new D_);
47    echo 'Pass', \PHP_EOL;
48} catch (\Throwable $throwable) {
49    echo $throwable->getMessage(), \PHP_EOL;
50}
51
52// Lets try in reverse?
53try {
54    $t->method2(new A_);
55    echo 'Fail', \PHP_EOL;
56} catch (\Throwable $throwable) {
57    echo $throwable->getMessage(), \PHP_EOL;
58}
59
60try {
61    $t->method2(new B_);
62    echo 'Fail', \PHP_EOL;
63} catch (\Throwable $throwable) {
64    echo $throwable->getMessage(), \PHP_EOL;
65}
66
67try {
68    $t->method2(new AB_);
69    echo 'Pass', \PHP_EOL;
70} catch (\Throwable $throwable) {
71    echo $throwable->getMessage(), \PHP_EOL;
72}
73
74try {
75    $t->method2(new D_);
76    echo 'Pass', \PHP_EOL;
77} catch (\Throwable $throwable) {
78    echo $throwable->getMessage(), \PHP_EOL;
79}
80
81/* Single before intersection */
82try {
83    $t->method3(new A_);
84    echo 'Fail', \PHP_EOL;
85} catch (\Throwable $throwable) {
86    echo $throwable->getMessage(), \PHP_EOL;
87}
88
89try {
90    $t->method3(new B_);
91    echo 'Fail', \PHP_EOL;
92} catch (\Throwable $throwable) {
93    echo $throwable->getMessage(), \PHP_EOL;
94}
95
96try {
97    $t->method3(new AB_);
98    echo 'Pass', \PHP_EOL;
99} catch (\Throwable $throwable) {
100    echo $throwable->getMessage(), \PHP_EOL;
101}
102
103try {
104    $t->method3(new D_);
105    echo 'Pass', \PHP_EOL;
106} catch (\Throwable $throwable) {
107    echo $throwable->getMessage(), \PHP_EOL;
108}
109
110// Lets try in reverse?
111try {
112    $t->method4(new A_);
113    echo 'Fail', \PHP_EOL;
114} catch (\Throwable $throwable) {
115    echo $throwable->getMessage(), \PHP_EOL;
116}
117
118try {
119    $t->method4(new B_);
120    echo 'Fail', \PHP_EOL;
121} catch (\Throwable $throwable) {
122    echo $throwable->getMessage(), \PHP_EOL;
123}
124
125try {
126    $t->method4(new AB_);
127    echo 'Pass', \PHP_EOL;
128} catch (\Throwable $throwable) {
129    echo $throwable->getMessage(), \PHP_EOL;
130}
131
132try {
133    $t->method4(new D_);
134    echo 'Pass', \PHP_EOL;
135} catch (\Throwable $throwable) {
136    echo $throwable->getMessage(), \PHP_EOL;
137}
138
139
140?>
141--EXPECTF--
142T::method1(): Argument #1 ($arg) must be of type (A&B)|D, A_ given, called in %s on line %d
143T::method1(): Argument #1 ($arg) must be of type (A&B)|D, B_ given, called in %s on line %d
144Pass
145Pass
146T::method2(): Argument #1 ($arg) must be of type (B&A)|D, A_ given, called in %s on line %d
147T::method2(): Argument #1 ($arg) must be of type (B&A)|D, B_ given, called in %s on line %d
148Pass
149Pass
150T::method3(): Argument #1 ($arg) must be of type D|(A&B), A_ given, called in %s on line %d
151T::method3(): Argument #1 ($arg) must be of type D|(A&B), B_ given, called in %s on line %d
152Pass
153Pass
154T::method4(): Argument #1 ($arg) must be of type D|(B&A), A_ given, called in %s on line %d
155T::method4(): Argument #1 ($arg) must be of type D|(B&A), B_ given, called in %s on line %d
156Pass
157Pass
158