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