On Tue, Feb 3, 2026, at 10:22, Nicolas Grekas wrote:
>
>
> Le mar. 3 févr. 2026 à 10:00, Rob Landers <[email protected]> a écrit :
>> __
>> On Tue, Feb 3, 2026, at 09:56, Nicolas Grekas wrote:
>>> Hi Rob,
>>>
>>> Le mar. 3 févr. 2026 à 09:50, Rob Landers <[email protected]> a écrit :
>>>> __
>>>> On Mon, Feb 2, 2026, at 22:14, Nicolas Grekas wrote:
>>>>> Hi Marco,
>>>>>
>>>>> Le lun. 2 févr. 2026 à 11:54, Marco Pivetta <[email protected]> a écrit :
>>>>>> Hey Nicolas,
>>>>>>
>>>>>>
>>>>>> On Thu, 22 Jan 2026 at 16:34, Nicolas Grekas
>>>>>> <[email protected] <mailto:nicolas.grekas%[email protected]>>
>>>>>> wrote:
>>>>>>> Dear all,
>>>>>>>
>>>>>>> Here is a new RFC for you to consider:
>>>>>>> https://wiki.php.net/rfc/promoted_readonly_constructor_reassign
>>>>>>
>>>>>>
>>>>>> What happens if one calls `$obj->__construct(1, 2, 3)` (on an already
>>>>>> instantiated `$obj`) in the context of this patch?
>>>>>
>>>>> Thanks for asking, I didn't think about this. This made me also think
>>>>> about ReflectionClass::newInstanceWithoutConstructor().
>>>>> I clarified this in the RFC, see "Direct __construct() Calls Cannot
>>>>> Bypass Readonly" and "Reflection: Objects Created Without Constructor".
>>>>> Patch and PR updated also if anyone wants to run some code where this RFC
>>>>> can be played with.
>>>>>
>>>>> Cheers,
>>>>> Nicolas
>>>>
>>>> Hi Nicolas,
>>>>
>>>> Under "Child Classes Can Reassign Parent Properties": this feels like a
>>>> major footgun. Calling parent::__construct() won't allow a reset (per the
>>>> rules of calling a constructor directly); which would completely break
>>>> inheritance... but then in the examples it says that calling a constructor
>>>> directly can reset it -- but you can't?
>>>>
>>>> This feels really inconsistent to me.
>>>>
>>>> — Rob
>>>
>>> Yes, the text was ambiguous. The implementation allows
>>> parent::__construct() during the initial construction (normal inheritance),
>>> and only blocks explicit __construct() calls after construction completed.
>>> I’ve clarified this in the RFC.
>>>
>>> Nicolas
>>
>> Will this result in a catchable error? I assume so, so a valid pattern
>> during inheritance might be to put these in a try/catch so children can set
>> them first?
>>
>> FWIW, in my Records RFC, properties were fully mutable during construction
>> for exactly this reason.
>>
>>
>
> The existing behavior is preserved: if a reassignment fails, it throws a
> catchable Error. The implicit CPP assignment in a parent constructor happens
> before the parent body, so a child cannot "set first" and then call
> ''parent::__construct()'' to avoid it; a try/catch in the parent cannot
> intercept it. But a try/catch in the child can catch of course.
>
> Does that answer your question?
So, this could end up with partial application of state? Or does it rollback?
For example:
class Box {
public function __construct(readonly int $x, readonly int $y, readonly bool
$isSquare = false) {
$this->isSquare = $x == $y;
}
}
class Square extends Box {
public function __construct(readonly int $size) {
$this->isSquare = true;
try {
parent::__construct($size, $size); // what is the state after it throws?
} catch(\Throwable) {}
}
}
(I spent over a year thinking about this stuff ... so if you're interested in
more edge cases, I can dig up my notes)
— Rob