Hi everyone,

Le jeu. 19 févr. 2026 à 10:49, Nicolas Grekas <[email protected]>
a écrit :

> Hi Tim,
>
> Le mer. 18 févr. 2026 à 22:29, Tim Düsterhus <[email protected]> a écrit :
>
>> Hi
>>
>> On 2/16/26 19:20, Nicolas Grekas wrote:
>> > To be sure I understood you well: you are suggesting that mutability
>> should
>> > be scoped to the constructor that declares the property (not any
>> > constructor on the object).
>>
>> Yes, because otherwise you might rely on implementation details of the
>> parent constructor: Depending on whether the parent constructor
>> reassigns internally, your reassignment in the child constructor either
>> succeeds or fails.
>>
>> > This makes sense and I’ve implemented exactly that model:
>> > - Reassignment is allowed only while the declaring class constructor is
>> > active (including methods/closures called from it).
>> > - A child constructor can no longer reassign a parent-declared promoted
>> > readonly property.
>> > - “Child sets first, then parent::__construct()” now throws as expected.
>> > - The thrown Error is catchable from the child (around
>> > parent::__construct()), but not from inside the parent body before
>> implicit
>> > CPP init.
>> > - Calling __construct() on an already-constructed object still cannot
>> > mutate readonly state.
>> >
>> > I also updated the RFC text and examples to state this explicitly, and
>> > added/updated tests for the inheritance/preemption scenarios.
>>
>> Thank you. I've checked the RFC and the explanation and semantics make
>> sense to me. I've also reviewed (parts) of the tests and provided some
>> feedback there. I'll take another look at the tests when you made the
>> adjustments to make sure that everything in the RFC is properly tested
>> to make sure we didn't miss and edge case.
>>
>> > Anything else?
>>
>> Yes, there is one edge case related to inheritance that isn't mentioned
>> in the RFC and from what I see it's not tested either.
>>
>> Child classes can redefine readonly properties and they are then “owned”
>> by the child class. Thus we need to explain what happens in that case.
>> I've prepared example for the three relevant cases I can think of. The
>> follow from the existing semantics in a straight-forward fashion, but
>> it's good to spell them out explicitly (and particularly test them).
>>
>> 1. Parent uses CPP, child redefines and reassigns.
>>
>>      class P1 {
>>          public function __construct(
>>              public readonly string $x = 'P',
>>          ) { }
>>      }
>>
>>      class C1 extends P1 {
>>          public readonly string $x;
>>
>>          public function __construct() {
>>              parent::__construct();
>>
>>              $this->x = 'C'; // This should fail.
>>          }
>>      }
>>
>> 2. Parent uses CPP and reassigns, child redefines.
>>
>>      class P2 {
>>          public function __construct(
>>              public readonly string $x = 'P1',
>>          ) {
>>              $this->x = 'P2'; // This should be legal.
>>          }
>>      }
>>
>>      class C2 extends P2 {
>>          public readonly string $x;
>>
>>          public function __construct() {
>>              parent::__construct();
>>          }
>>      }
>>
>> 3. Parent uses CPP, child uses CPP redefinition.
>>
>>      class P3 {
>>          public function __construct(
>>              public readonly string $x = 'P',
>>          ) { }
>>      }
>>
>>      class C3 extends P3 {
>>          public function __construct(
>>              public readonly string $x = 'C1',
>>          ) {
>>              parent::__construct(); // This should fail.
>>          }
>>      }
>>
>>
>
> Thanks, I've added new test cases to cover this.
> I've also improved tests as suggested on the PR.
> And finally I updated the implementation to reuse IS_PROP_REINITABLE
> instead of adding new flags + use an approach that doesn't require walking
> the call stack.
> PR and RFC updated accordingly, all green.
>

One last update following more review comments by Tim:  the reassign window
is now scoped to the CPP-owning constructor.
See updated wording at
https://wiki.php.net/rfc/promoted_readonly_constructor_reassign

Cheers,
Nicolas

Reply via email to