parent
61099c4c9e
commit
72db18c22a
7 changed files with 237 additions and 108 deletions
@ -0,0 +1,13 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
interface InterfaceParamUnionNarrowsMixed |
||||||
|
{ |
||||||
|
public function value(mixed $v); |
||||||
|
} |
||||||
|
|
||||||
|
class InterfaceParamUnionNarrowsMixedImpl implements InterfaceParamUnionNarrowsMixed |
||||||
|
{ |
||||||
|
public function value(string|int $v) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
interface InterfaceParamUnionNarrowsUntyped |
||||||
|
{ |
||||||
|
public function value($v); |
||||||
|
} |
||||||
|
|
||||||
|
class InterfaceParamUnionNarrowsUntypedImpl implements InterfaceParamUnionNarrowsUntyped |
||||||
|
{ |
||||||
|
public function value(string|int $v) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
@ -1,104 +1,105 @@ |
|||||||
--TEST-- |
--TEST-- |
||||||
Class implements interface: union type / composite type parameter compatibility |
Class implements interface: parameter type compatibility |
||||||
Tests parameter type contravariance for interface implementation with union types: |
--FILE-- |
||||||
- Child method omitting the type should accept a wider set of inputs. |
<?php |
||||||
- Child method declaring the identical union type should also compile. |
|
||||||
- nullable union (T1|T2|null) and three-way union (T1|T2|T3) are covered. |
interface ContractA |
||||||
--FILE-- |
{ |
||||||
<?php |
public function single(string $value); |
||||||
|
public function union2(string|int $value); |
||||||
// ------------------------------------------------------- |
public function union3(string|int|float $value); |
||||||
// Interface with single + union type parameters |
public function nullableUnion(string|int|null $value); |
||||||
// ------------------------------------------------------- |
} |
||||||
interface ContractA |
|
||||||
{ |
class ImplOmitAll implements ContractA |
||||||
public function single(string $value); |
{ |
||||||
public function union2(string|int $value); |
public function single($value) { var_dump($value); } |
||||||
public function union3(string|int|float $value); |
public function union2($value) { var_dump($value); } |
||||||
public function nullableUnion(string|int|null $value); |
public function union3($value) { var_dump($value); } |
||||||
} |
public function nullableUnion($value) { var_dump($value); } |
||||||
|
} |
||||||
// Child omits every parameter type — must be compatible with all. |
|
||||||
class ImplOmitAll implements ContractA |
interface ContractB |
||||||
{ |
{ |
||||||
public function single($value) { var_dump($value); } |
public function mirror(string|int $x); |
||||||
public function union2($value) { var_dump($value); } |
} |
||||||
public function union3($value) { var_dump($value); } |
|
||||||
public function nullableUnion($value) { var_dump($value); } |
class ImplMirror implements ContractB |
||||||
} |
{ |
||||||
|
public function mirror(string|int $x) |
||||||
// ------------------------------------------------------- |
{ |
||||||
// Interface where child mirrors the union type exactly |
var_dump($x); |
||||||
// ------------------------------------------------------- |
} |
||||||
interface ContractB |
} |
||||||
{ |
|
||||||
public function mirror(string|int $x); |
interface ContractC |
||||||
} |
{ |
||||||
|
public function widen(string $v); |
||||||
class ImplMirror implements ContractB |
} |
||||||
{ |
|
||||||
public function mirror(string|int $x) |
class ImplWiden implements ContractC |
||||||
{ |
{ |
||||||
var_dump($x); |
public function widen(string|int $v) |
||||||
} |
{ |
||||||
} |
var_dump($v); |
||||||
|
} |
||||||
// ------------------------------------------------------- |
} |
||||||
// Multiple interfaces with different union types |
|
||||||
// ------------------------------------------------------- |
interface ContractD |
||||||
interface ContractC |
{ |
||||||
{ |
public function a(string|bool $v); |
||||||
public function a(string|bool $v); |
} |
||||||
} |
|
||||||
interface ContractD |
interface ContractE |
||||||
{ |
{ |
||||||
public function b(int|float $v); |
public function b(int|float $v); |
||||||
} |
} |
||||||
|
|
||||||
class ImplMulti implements ContractC, ContractD |
class ImplMulti implements ContractD, ContractE |
||||||
{ |
{ |
||||||
public function a($v) { var_dump($v); } |
public function a($v) { var_dump($v); } |
||||||
public function b($v) { var_dump($v); } |
public function b($v) { var_dump($v); } |
||||||
} |
} |
||||||
|
|
||||||
function main() |
function main() |
||||||
{ |
{ |
||||||
// ImplOmitAll — omitted types should still pass runtime checks |
$a = new ImplOmitAll; |
||||||
$a = new ImplOmitAll; |
$a->single('hello'); |
||||||
$a->single('hello'); |
$a->union2('world'); |
||||||
$a->union2('world'); |
$a->union2(42); |
||||||
$a->union2(42); |
$a->union3(1); |
||||||
$a->union3(1); |
$a->union3('two'); |
||||||
$a->union3('two'); |
$a->union3(3.14); |
||||||
$a->union3(3.14); |
$a->nullableUnion(100); |
||||||
$a->nullableUnion(100); |
$a->nullableUnion(null); |
||||||
$a->nullableUnion(null); |
|
||||||
|
$b = new ImplMirror; |
||||||
// ImplMirror — explicit matching union type |
$b->mirror('ok'); |
||||||
$b = new ImplMirror; |
$b->mirror(99); |
||||||
$b->mirror('ok'); |
|
||||||
$b->mirror(99); |
$c = new ImplWiden; |
||||||
|
$c->widen('wide'); |
||||||
// ImplMulti — multiple interfaces |
|
||||||
$c = new ImplMulti; |
$d = new ImplMulti; |
||||||
$c->a('yes'); |
$d->a('yes'); |
||||||
$c->a(true); |
$d->a(true); |
||||||
$c->b(123); |
$d->b(123); |
||||||
$c->b(4.56); |
$d->b(4.56); |
||||||
} |
} |
||||||
?> |
?> |
||||||
--EXPECT-- |
--EXPECT-- |
||||||
string(5) "hello" |
string(5) "hello" |
||||||
string(5) "world" |
string(5) "world" |
||||||
int(42) |
int(42) |
||||||
int(1) |
int(1) |
||||||
string(3) "two" |
string(3) "two" |
||||||
float(3.14) |
float(3.14) |
||||||
int(100) |
int(100) |
||||||
NULL |
NULL |
||||||
string(2) "ok" |
string(2) "ok" |
||||||
int(99) |
int(99) |
||||||
string(3) "yes" |
string(4) "wide" |
||||||
bool(true) |
string(3) "yes" |
||||||
int(123) |
bool(true) |
||||||
float(4.56) |
int(123) |
||||||
|
float(4.56) |
||||||
|
|||||||
Loading…
Reference in new issue