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

Reply via email to