On Mon, Jun 29, 2026, at 18:59, Larry Garfield wrote:
[snip]
> The RFC has no mention of attributes. An example of that would be helpful,
> even though I presume it's exactly what one would expect it to be.
This was an oversight. I'll add the logic there. This is how they work:
1. Attributes on promoted primary-constructor params are reflected on both
(just like promoted properties):
1. ReflectionParameter
2. ReflectionProperty
2. Attributes on bare params remain parameter-only.
3. Target validation is context-sensitive, matching existing constructor
promotion behavior:
1. `#[ParamAttr] public int $x` appears on the property too, but
newInstance() from ReflectionProperty errors.
2. `#[PropAttr] public int $x` appears on the parameter too, but
newInstance() from ReflectionParameter errors.
4. Attributes before a class remain class attributes and are not copied to the
synthesized constructor.
The last one is debatable, but from what I can tell from grepping, putting
attributes on constructors is a very rare thing (39 out of 56,546
constructors). However, class-level attributes are a more common thing. That
being said, I'd be open to changing (4) to behave like properties/parameters
where it gets attached to the class and the constructor.
> The one addition I would ask for is to note that in Kotlin and Swift, there
> is a post-primary-constructor initializer, called an `init` block. It has no
> body, but lets you do post-property-assignment stuff. It's basically an
> argument-free constructor. I think that would go a long way toward smoothing
> the concerns people have about this feature being too "locked down."
>
> If we don't want a new keyword for it, we could allow a __construct method
> that has NO arguments if there is a primary constructor. It would get called
> last, after everything else (including parent constructors if appropriate)
> has run. (Whether it's spelled `__construct() { ]]` or `__construct { }`, I
> don't have a strong opinion.) A __construct that does take arguments would
> still be a compile-time conflict with a primary constructor.
>
> --Larry Garfield
>
I believe this should be a follow-up RFC. In PHP, the child decides when to
call the parent constructor — so "runs last, after parent constructors"
requires defining a new sequencing contract, which is a real design decision
that deserves its own discussion rather than a rider on this one. Beyond that,
it also requires defining a syntax (you've sketched one approach, Nick another
-- both are interesting and that's exactly why it needs its own discussion),
rules (whether property lists should exist), and semantics. In essence, the
description would be a large (probably half) of the current RFC.
— Rob