Add $this return type

php.internals

radar3301

2 years ago
I'm looking for initial feedback on the following proposal. Often, we have the following (fluent interface) setter method: public function setName(?string $name): static { $this->name = $name; return $this; } I propose to add "$this" as a return type, ie: public function setName(?string $name): $this { $this->name = $name; // implicit return $this; } public function setName(?string $name): $this { $this->name = $name; // this would be an (compiler?) error return $somethingOtherThanThis; } public function setName(?string $name): $this { $this->name = $name; $self = $this; // this would not be an error return $self; } public function setName(?string $name): $this { $this->name = $name; // technically useless, but not an error return $this; } public function setName(?string $name): $this { $this->name = $name; if ('foobar' === $name) { // not an error to return early return; } // do some other stuff // any of the above legal examples } It should be obvious, but functions outside of a class context would not be able to use this syntax. BC: There would be no BC breaks, as this syntax is currently invalid (Parse error: syntax error, unexpected variable "$this"). Other Considerations: With regards to reflection and inheritance, "$this" would be considered an alias for "static". Regards, radar3301

Luigi Cardamone

2 years ago
On Tue, Jun 25, 2024 at 2:29 AM radar3301 <radar3301@gmail.com> wrote:
> I'm looking for initial feedback on the following proposal. > > Often, we have the following (fluent interface) setter method: > > public function setName(?string $name): static > { > $this->name = $name; > > return $this; > } > > I propose to add "$this" as a return type, ie: > > public function setName(?string $name): $this > { > $this->name = $name; > // implicit return $this; > } > > public function setName(?string $name): $this > { > $this->name = $name; > // this would be an (compiler?) error > return $somethingOtherThanThis; > } > > public function setName(?string $name): $this > { > $this->name = $name; > $self = $this; > // this would not be an error > return $self; > } > > public function setName(?string $name): $this > { > $this->name = $name; > // technically useless, but not an error > return $this; > } > > public function setName(?string $name): $this > { > $this->name = $name; > if ('foobar' === $name) { > // not an error to return early > return; > } > // do some other stuff > > // any of the above legal examples > } > > It should be obvious, but functions outside of a class context would not > be able to use this syntax. > > BC: > There would be no BC breaks, as this syntax is currently invalid (Parse > error: syntax error, unexpected variable "$this"). > > Other Considerations: > With regards to reflection and inheritance, "$this" would be considered an > alias for "static". > > Regards, > radar3301 >
I strongly agree that an alias for the "static" keyword is really necessary to improve the semantics of the language. The word "static" is used for many things: static methods, static classes and Late Static Bindings (that is the case that you are discussing). I think that in the case of Late Static Bindings (e.g. `new static()` or return type `..(): static`), the word "static" does not give any clue about the meaning of that code. Thus, I like your proposal. The part that I do not like is the implicit return: it may confuse developers and static analysis tools. Is it possible to replace "$this" with "this"? Cleaner and coherent with "self". Regards, Luigi

Weirdan

2 years ago
On Tue, Jun 25, 2024 at 9:51 AM Luigi Cardamone <cardamoneluigi@gmail.com> wrote:
> > Is it possible to replace "$this" with "this"? Cleaner and coherent with > "self". >
That wouldn't be possible, as `this` is a valid class name: https://3v4l.org/ujGOT
-- Best regards, Bruce Weirdan mailto: weirdan@gmail.com

Alexandru Pătrănescu

2 years ago
On Tue, Jun 25, 2024 at 3:28 AM radar3301 <radar3301@gmail.com> wrote:
> I'm looking for initial feedback on the following proposal. > > I propose to add "$this" as a return type, ie: > >
Worth reading: - the previous RFC that didn't got to a voting stage: https://wiki.php.net/rfc/this_return_type - the discussion thread: https://externals.io/message/115986

radar3301

2 years ago
@Alexandru:
> Worth reading:
Ah shoot, my search-fu failed me (it's not listed on the RFC page, and I suppose I was not using the right search terms). I'm glad to find out this rfc previously existed, and in that case, I guess I'd like to revive that discussion. :) @Luigi:
> The part that I do not like is the implicit return: it may confuse developers and static analysis > tools.
I understand the implicit return may be somewhat confusing, but one of the secondary driving factors, aside from a much clearer API signature (without requiring a docblock comment), and engine enforced object safety, was the benefit of reduced "boilerplate" code. However, I suppose I can accept that this may not be possible, but I would like to discuss it as a potential option. However, I disagree with you about the static analysis tools.
> Is it possible to replace "$this" with "this"? Cleaner and coherent with "self".
I actually thought about this a bit before posting, and I came to the same conclusion as Nicolas, i.e.: /** * @return $this */ To quote Nicolas:
> About the syntax, I think the one proposed in the RFC is crystal clear. I've been used to seeing > the "$" symbol [snip]
More on this below. @previous commenters on the old thread Andreas Heigl said:
> If we allow a $this [snip] as a returntype to clarify that it has to be the same instance that is > returned, I would also either expect that the returntype 'self' does explicitly not allow the > same instance to be returned. As that would be a huge BC break [snip] we should implement a > returntype "!$this" to explicitly state that the contract here returns not the current instance > but a new one.
Strongly disagree. This would be too much of a BC, and I don't really see the benefit, even allowing for a "!$this"-style returntype. I'm not opposed to a separate RFC or discussion regarding this, but I don't feel it's appropriate here. Sebastian Bergmann said:
> [snip] please not "$this" as the name for a type. > Off the top of my head, I think that "same" could make sense.
My primary vote would still be for "$this" as explained above, but I could potentially be persuaded to switch to "this" or "same" as alternatives if the dollar-sign is too much of a hang-up. Regards, radar3301

Unnamed Person

2 years ago
On 25-6-2024 19:53, radar3301 wrote:
> Sebastian Bergmann said: >> [snip] please not "$this" as the name for a type. >> Off the top of my head, I think that "same" could make sense. > My primary vote would still be for "$this" as explained above, but I > could potentially be persuaded > to switch to "this" or "same" as alternatives if the dollar-sign is > too much of a hang-up.
Not a fan of using a variable as a return type. This will cause havoc for Tokenizer based static analysis tooling. Not a fan of the implicit return either. Also don't really see the need as there is the `static` return type already.

Marco Pivetta

2 years ago
On Tue, 25 Jun 2024 at 23:25, Juliette Reinders Folmer < php-internals_nospam@adviesenzo.nl> wrote:
> Also don't really see the need as there is the `static` return type > already. >
I'd see it as useful if the type conveyed identity too, although it also means that I would never use it, since I design immutable APIs, when possible :D Marco Pivetta https://mastodon.social/@ocramius https://ocramius.github.io/

radar3301

2 years ago
Juliette Reinders Folmer said:
> Not a fan of using a variable as a return type. This will cause > havoc for Tokenizer based static analysis tooling.
I will concede that until the tools are updated to handle the new (currently invalid) syntax, it would cause issues. But that happens everytime a new syntax is introduced into PHP anyway (the original return-types RFC, match, the proposed property accessors, etc.), so I'm a bit confused as why this is an issue that would stop the RFC? --- Juliette Reinders Folmer said:
> Also don't really see the need as there is the `static` return type > already.
To quote Nicolas, who said it far better than I could:
> I tried switching from the `@return $this` annotation to > `function (): static`, which is the closest approximation currently > supported by the engine, when I realized that this would loosen the > semantics of the corresponding interfaces[.]
--- Marco Pivetta said:
> I'd see it as useful if the type conveyed identity too, although it > means that I would never use it, since I design immutable APIs, when > possible :D
If reading documentation, I'd argue that seeing `function(): $this` in a class already conveys plenty of "identity". If you're talking about using the Reflection API to get identity the original RFC by Nikita stated:
> The `$this` type is a subtype of `static`. As such, it is possible > to restrict a `static` type to `$this` in a subclass (but not the > other way around). > In reflection, the `$this` type is represented as a > `ReflectionNamedType` with `isBuiltin() == true` and > `getName() == "$this"`.
So perhaps a change is needed in the returned `ReflectionNamedType` to better identity the actual class of `$this`? Or am I missing your point about identity here? --- Bruce Weirdan said:
>> Luigi Cardamone wrote: >> Is it possible to replace "$this" with "this"? Cleaner and coherent >> with "self". > > That wouldn't be possible, as `this` is a valid class name:
The "Return Type Declarations", "Scalar Type Declarations", "Reserve More Types", and "Void Return Type" RFCs all prohibited their usage as class, interface and trait names. Using `this` or `same` or `whatever` else is decided is just par for the course. However, that said, a search of github for: - `language:php "class This "` returns 5.1k results (but it appears that most results are docblock comments) - `language:php "class This extends"` returns 27 results - `language:php "class This implements"` returns 8 results - `language:php "class Same "` returns 290 results - `language:php "class Same extends"` returns 193 results - `language:php "class Same implements"` returns 14 results - `language:php "@return $this"` returns 485k results. --- Regards, radar3301