Re: [RFC] Primary Constructors
| From: | Lynn | Date: | Mon, 29 Jun 2026 11:30:00 +0000 |
| Subject: | Re: [RFC] Primary Constructors | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-131579@lists.php.net to get a copy of this message | ||
On Mon, Jun 29, 2026 at 12:56 PM Rob Landers <rob@getswytch.com> wrote:
>
>
> On Mon, Jun 29, 2026, at 12:27, Lynn wrote:
>
>
>
> On Mon, Jun 29, 2026 at 2:20 AM Rob Landers <rob@getswytch.com> wrote:
>
>
> Hello internals,
>
> I'd like to put forward Primary Constructors
> <https://wiki.php.net/rfc/primary-constructors> for
> comment.
>
> An implementation PR will be opened later today (UTC), and the RFC updated
> with this discussion thread.
>
> — Rob
>
>
> I don't see any mention of anonymous classes, I assume they aren't
> compatible syntax wise?
>
>
> Hi Lynn,
>
> That's a good observation! Originally, I had a whole section and decided
> to strip it, then forgot to add it back as non-supported and future scope..
> FWIW, I was originally going to support them with something like:
>
> $arg = 'foo';
> $class = new class(public int $x = $arg) {}
>
>
> Which desugars to:
>
> $arg = 'foo';
> $class = new class($arg) {
> public function __construct(public int $x) {}
> }
>
>
> There are a lot of caveats, which is why I dropped it for future scope:
>
> 1. it would require types on the input parameters to disambiguate
> between arguments and properties
> 2. it gets weird if you don't specify a default value for the property
> and makes it ambiguous as a constructor
> 3. which begs the question of always having a default
>
> In essence, it deserves its own RFC because there is a lot of subtlety and
> only makes sense in the context that primary constructors exist in the
> first place.
>
> I'll address it in the RFC, thanks!
>
> — Rob
>
I think the only thing that needs to be solved for anonymous classes would
be the syntax. Seeing there's always a visibility/type in property
promotion, I think it should be clear it's going to be style (A) or (B)
based on the syntax as you can't mix. I can't see a scenario where you
would write:
$class = new class(public int $x) {}
Where as the following would be just fine:
$class = new class(public int $x = 0) {}; // construct with
property $x being 0
$class = new class(public int|null $x = null) {}; // construct with
property $x being null
$class = new class(public int $x = $x) {}; // construct with
$x from local scope into property $x
$class = new class(public int $x = $this->x) {}; // construct with
$this->x from the instance scope
$class = new class(public int $x = self::$x) {}; // construct with
$this->x from the static self scope
Bonus points if the body becomes optional:
$class = new class(public int $x = 0, public int $y = 0);
This would be the existing style and remains unchanged
$class = new class($localScope) {};
Mixing would error as you can't pick both:
$class = new class(public int $x = 0, $y) {}; // Nothing handles $y as
no body is allowed
$class = new class($x, public int $y = 0) {}; // Can't allow the
latter as $x requires a body to do something
Perhaps this isn't as simple as I think it is, but this would be a nice +
to have in this RFC. I think it's fine to keep the initial implementation
rather restrictive, it can always be improved upon in the future.