Skip to content

PHP8.2: (A&B)|D as a param should allow AB or D. Not just A. #9516

Closed
@kschatzle

Description

@kschatzle

Description

The following code:

<?php

interface A { }
interface B { }
interface D { }

class A_ implements A {}
class B_ implements B {}
class AB_ implements A, B {}
class D_ implements D {}

class T {
    public function method((A&B)|D $arg): void {}
    public function method2((B&A)|D $arg): void {}
}

$t = new T;

try {
    $t->method(new A_);     // Bug?
    echo 'Fail', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method(new B_);
    echo 'Fail', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method(new AB_);
    echo 'Pass', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method(new D_);
    echo 'Pass', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

// Lets try in reverse?
try {
    $t->method2(new A_);
    echo 'Fail', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method2(new B_);     // Bug?
    echo 'Fail', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method2(new AB_);
    echo 'Pass', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}

try {
    $t->method2(new D_);
    echo 'Pass', \PHP_EOL;
} catch (\Throwable $throwable) {
    echo $throwable->getMessage(), \PHP_EOL;
}


?>

Resulted in this output:

Fail
T::method(): Argument #1 ($arg) must be of type (A&B)|D, B_ given, called in %s on line %d
Pass
Pass
T::method2(): Argument #1 ($arg) must be of type (B&A)|D, A_ given, called in %s on line %d
Fail
Pass
Pass

But I expected this output instead:

T::method(): Argument #1 ($arg) must be of type (A&B)|D, A_ given, called in %s on line %d
T::method(): Argument #1 ($arg) must be of type (A&B)|D, B_ given, called in %s on line %d
Pass
Pass
T::method2(): Argument #1 ($arg) must be of type (B&A)|D, A_ given, called in %s on line %d
T::method2(): Argument #1 ($arg) must be of type (B&A)|D, B_ given, called in %s on line %d
Pass
Pass

PHP Version

PHP 8.2.0-dev

Operating System

macOS Monterey Version 12.5.1 arm64

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions