php / php-src

The PHP Interpreter
https://www.php.net
Other
38.35k stars 7.77k forks source link

False error when property incompatibility in a class and a trait if the property is defined in the constructor. #16525

Closed EdmondDantes closed 1 month ago

EdmondDantes commented 1 month ago

Description

The following code:

trait someTrait
{
    protected array $attributes = [];
}

class test
{
    use someTrait;

    public function __construct(
        protected array $attributes = []
    ) {}
}

$test = new test([1,2,3]);

Resulted in this output:

Fatal error: test and someTrait define the same property ($attributes) in the composition of test. However, the definition differs and is considered incompatible. Class was composed in test.php on line 11

But I expected this output instead:

No errors

P.S. If the property is defined outside the constructor, everything works fine!

PHP Version

PHP 8.3.4

Operating System

Windows 11

devnexen commented 1 month ago

cc @iluuu1994

iluuu1994 commented 1 month ago

Hi @EdmondDantes.

https://wiki.php.net/rfc/constructor_promotion#desugaring

class test {
    public function __construct(
        protected array $attributes = []
    ) {}
}

desugars to

class test {
    protected array $attributes;
    public function __construct(array $attributes = []) { ... }
}

As you can see, the default value is declared on the parameter, not the property. This doesn't usually matter, but it can, e.g. when using ReflectionClass::newInstanceWithoutConstructor(). So, this is not a bug. The only way to avoid this would be to declare the default value on both the parameter and the property. But as the RFC explains, this would lead to other issues. It's also breaking, as sub-classes would now need to specify a default value on the property if they don't use constructor property promotion. Hence, I'm afraid this does not have a solution.

EdmondDantes commented 1 month ago

@iluuu1994 Thank you for the remark. Indeed, if the property is declared without a default value, such behavior becomes understandable.