Constructor property promotion for final properties

php.internals

Daniel Scherzer

1 year ago
Hi internals, I recently found out that constructor property promotion cannot be used for final properties. I propose that it become allowed. Thoughts? Would this need an RFC, or is this minor enough to be acceptable with just a mailing list discussion? Background: In the process of trying to help support PHP 8.4 syntax in PHPCS[1], I discovered that constructor property promotion cannot be used with final properties. I thought that this was a bug, and filed GH-17860 with the report[2]. But, in the discussion on the patch that I sent to fix the bug[3], I was told that this was intentionally omitted. So, now the bug is a feature request. -Daniel [1] https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/734 [2] https://github.com/php/php-src/issues/17860 [3] https://github.com/php/php-src/issues/17861

Daniel Scherzer

1 year ago
On Fri, Feb 21, 2025 at 12:09 PM Daniel Scherzer < daniel.e.scherzer@gmail.com> wrote:
> Hi internals, > > I recently found out that constructor property promotion cannot be used > for final properties. I propose that it become allowed. Thoughts? Would > this need an RFC, or is this minor enough to be acceptable with just a > mailing list discussion? >
Given the lack of engagement, I want to make it clear: unless somebody objects, maintainers have agreed to merge a PR implementing the feature in 2 weeks. If you object, please speak up. --Daniel

Tim Düsterhus

1 year ago
Hi Am 2025-03-20 21:12, schrieb Daniel Scherzer:
>> I recently found out that constructor property promotion cannot be >> used >> for final properties. I propose that it become allowed. Thoughts? >> Would >> this need an RFC, or is this minor enough to be acceptable with just a >> mailing list discussion? >> > > Given the lack of engagement, I want to make it clear: unless somebody > objects, maintainers have agreed to merge a PR implementing the feature > in > 2 weeks. > > If you object, please speak up.
Can you clarify if the following would result in constructor property promotion or not: class Foo { public function __construct( final string $bar, ) { } } Best regards Tim Düsterhus

Daniel Scherzer

1 year ago
On Fri, Mar 21, 2025 at 4:07 AM Tim Düsterhus <tim@bastelstu.be> wrote:
> Can you clarify if the following would result in constructor property > promotion or not: > > class Foo { > public function __construct( > final string $bar, > ) { } > } > > Best regards > Tim Düsterhus >
Yes, that would result in constructor property promotion. I'll need to retarget the original PR for master, but at https://github.com/php/php-src/pull/17861 you can see in `Zend/tests/property_hooks/final_prop_promoted_2.phpt` a very similar test case. --Daniel

Alexandru Pătrănescu

1 year ago
On Fri, Mar 21, 2025 at 5:20 PM Daniel Scherzer <daniel.e.scherzer@gmail.com> wrote:
> On Fri, Mar 21, 2025 at 4:07 AM Tim Düsterhus <tim@bastelstu.be> wrote: > >> Can you clarify if the following would result in constructor property >> promotion or not: >> >> class Foo { >> public function __construct( >> final string $bar, >> ) { } >> } >> >> Best regards >> Tim Düsterhus >> > > Yes, that would result in constructor property promotion. I'll need to > retarget the original PR for master, but at > https://github.com/php/php-src/pull/17861 you can see in > `Zend/tests/property_hooks/final_prop_promoted_2.phpt` a very similar test > case. > >
I see. Good catch Tim. Daniel, you don't have this exact test case there. Initially, in 8.0, only a visibility keyword would trigger the property promotion logic. Later, in 8.1, also the readonly keyword would trigger this and make the property public, without the need to mention the visibility: https://3v4l.org/Co0gl Now we want the same for the final keyword, to trigger the property promotion without having a visibility keyword, because like readonly, it would not be applicable to a parameter, but just to a property?
-- Alex

Daniel Scherzer

1 year ago
On Fri, Mar 21, 2025 at 9:45 AM Alexandru Pătrănescu <drealecs@gmail.com> wrote:
> > On Fri, Mar 21, 2025 at 5:20 PM Daniel Scherzer < > daniel.e.scherzer@gmail.com> wrote: > >> On Fri, Mar 21, 2025 at 4:07 AM Tim Düsterhus <tim@bastelstu.be> wrote: >> >>> Can you clarify if the following would result in constructor property >>> promotion or not: >>> >>> class Foo { >>> public function __construct( >>> final string $bar, >>> ) { } >>> } >>> >>> Best regards >>> Tim Düsterhus >>> >> >> Yes, that would result in constructor property promotion. I'll need to >> retarget the original PR for master, but at >> https://github.com/php/php-src/pull/17861 you can see in >> `Zend/tests/property_hooks/final_prop_promoted_2.phpt` a very similar test >> case. >> >> > I see. Good catch Tim. > Daniel, you don't have this exact test case there. > > Initially, in 8.0, only a visibility keyword would trigger the property > promotion logic. > Later, in 8.1, also the readonly keyword would trigger this and make the > property public, without the need to mention the visibility: > https://3v4l.org/Co0gl > > Now we want the same for the final keyword, to trigger the property > promotion without having a visibility keyword, > because like readonly, it would not be applicable to a parameter, but just > to a property? > > -- > Alex >
Sorry, I completely missed that part. Yes, that should trigger promotion, and if it doesn't then that is a bug in my implementation. When I retarget the PR to master I'll also add a test case for promotion from just using `final`. --Daniel

Alexandru Pătrănescu

1 year ago
On Fri, Mar 21, 2025 at 9:30 PM Daniel Scherzer <daniel.e.scherzer@gmail.com> wrote:
> > On Fri, Mar 21, 2025 at 9:45 AM Alexandru Pătrănescu <drealecs@gmail.com> > wrote: > >> >> On Fri, Mar 21, 2025 at 5:20 PM Daniel Scherzer < >> daniel.e.scherzer@gmail.com> wrote: >> >>> On Fri, Mar 21, 2025 at 4:07 AM Tim Düsterhus <tim@bastelstu.be> wrote: >>> >>>> Can you clarify if the following would result in constructor property >>>> promotion or not: >>>> >>>> class Foo { >>>> public function __construct( >>>> final string $bar, >>>> ) { } >>>> } >>>> >>>> Best regards >>>> Tim Düsterhus >>>> >>> >>> Yes, that would result in constructor property promotion. I'll need to >>> retarget the original PR for master, but at >>> https://github.com/php/php-src/pull/17861 you can see in >>> `Zend/tests/property_hooks/final_prop_promoted_2.phpt` a very similar test >>> case. >>> >>> >> I see. Good catch Tim. >> Daniel, you don't have this exact test case there. >> >> Initially, in 8.0, only a visibility keyword would trigger the property >> promotion logic. >> Later, in 8.1, also the readonly keyword would trigger this and make the >> property public, without the need to mention the visibility: >> https://3v4l.org/Co0gl >> >> Now we want the same for the final keyword, to trigger the property >> promotion without having a visibility keyword, >> because like readonly, it would not be applicable to a parameter, but >> just to a property? >> >> -- >> Alex >> > > Sorry, I completely missed that part. Yes, that should trigger promotion, > and if it doesn't then that is a bug in my implementation. When I retarget > the PR to master I'll also add a test case for promotion from just using > `final`. > >
Hi Daniel, When discussing the Aviz RFC, I also wrote on this topic. ( https://news-web.php.net/php.internals/123488) The main issue being that if we ever decide to use the final modifier for a parameter, it would not be possible. It is already now possible to use the readonly modifier for a parameter because of this, something I wasn't aware of until this topic. On the readonly doing the promotion by itself, I believe it was an internal decision (that we properly documented later), but it was not discussed on the mailing list as far as I know. Also, I believe there might not be an actual test that validates this behavior. Having said that, allowing final to trigger property promotion by itself is not such a problematic thing, IMO. I would have preferred forcing a visibility keyword to trigger property promotions, but the cat is out of the bag already. Also, allowing the final modifier for constructor parameters to be transformed as the final modifier for promoted properties is fine. I guess that if we ever decide to use a keyword for declared variables or parameters to disallow changing their values, we can go with some other keyword like const, val, etc.
-- Alex

Larry Garfield

1 year ago
On Fri, Mar 21, 2025, at 2:29 PM, Daniel Scherzer wrote:
>>> Yes, that would result in constructor property promotion. I'll need to retarget the original PR for master, but at https://github.com/php/php-src/pull/17861 you can see in `Zend/tests/property_hooks/final_prop_promoted_2.phpt` a very similar test case.
To answer the original question: I'm not against this change, but as it is a syntax change, I think it does warrant an RFC, even if it's a small/easy one. That's a good way to flesh out the edge cases like that. --Larry Garfield

Daniel Scherzer

1 year ago
On Mon, Mar 24, 2025 at 11:22 AM Larry Garfield <larry@garfieldtech.com> wrote:
> > To answer the original question: I'm not against this change, but as it is > a syntax change, I think it does warrant an RFC, even if it's a small/easy > one. That's a good way to flesh out the edge cases like that. > > --Larry Garfield >
Okay, I've created https://wiki.php.net/rfc/final_promotion - I'll send an official notification email separately, but just wanted to include a link in the original thread. --Daniel