Skip to content

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

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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions