[RFC][Discuss] Covariant return- and contravariant parameter- types

php.internals

Levi Morrison

7 years ago
I am happy to announce my latest RFC, [Covariant Returns and Contravariant Parameters][1], is open for discussion. If you do not recognize those terms then hopefully the introduction coupled with the [examples][2] will help. Here is one snippet that demonstrates covariant return types: <?php interface Repository { function fetch(int $id): ?Entity; } class UserFactory implements Repository { function fetch(int $id): ?UserEntity { /* Since UserEntity is an Entity, this is now allowed */ /* ... implementation ... */ } } ?> Covariant return types and contravariant parameter types are highly requested features; here are a few of the bug reports: * https://bugs.php.net/bug.php?id=71825 * https://bugs.php.net/bug.php?id=72442 * https://bugs.php.net/bug.php?id=75385 * https://bugs.php.net/bug.php?id=75823 There is a [preliminary implementation][3] that is available. It will not be rebased during discussion to allow people to check out the code and get updates without worrying about it breaking. The code quality can definitely be improved, and there are still a few todo comments in the code. Please do not discuss the items found in [Future Scope][4] as part of this thread, which includes discussing types such as `mixed`, `scalar`, `numeric`, etc. I look forward to your feedback, and especially with your experimentation with the implementation. Levi Morrison [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples [3]: https://github.com/php/php-src/compare/master...morrisonlevi:variance2 [4]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#future_scope

Marcos Passos

7 years ago
I'm waiting for it for a long time! Thank you for putting effort on this! Em seg, 26 de nov de 2018 às 19:26, Levi Morrison <levim@php.net> escreveu:

Michał Brzuchalski

7 years ago
Can't wait for it to happen! Thank you for your work and fixing object type. pon., 26 lis 2018 o 22:26 Levi Morrison <levim@php.net> napisał(a):
> I am happy to announce my latest RFC, [Covariant Returns and > Contravariant Parameters][1], is open for discussion. If you do not > recognize those terms then hopefully the introduction coupled with the > [examples][2] will help. Here is one snippet that demonstrates > covariant return types: > > <?php > interface Repository { > function fetch(int $id): ?Entity; > } > > class UserFactory implements Repository { > function fetch(int $id): ?UserEntity { > /* Since UserEntity is an Entity, this is now allowed */ > /* ... implementation ... */ > } > } > ?> > > Covariant return types and contravariant parameter types are highly > requested features; here are a few of the bug reports: > > * https://bugs.php.net/bug.php?id=71825 > * https://bugs.php.net/bug.php?id=72442 > * https://bugs.php.net/bug.php?id=75385 > * https://bugs.php.net/bug.php?id=75823 > > There is a [preliminary implementation][3] that is available. It will > not be rebased during discussion to allow people to check out the code > and get updates without worrying about it breaking. The code quality > can definitely be improved, and there are still a few todo comments in > the code. > > Please do not discuss the items found in [Future Scope][4] as part of > this thread, which includes discussing types such as `mixed`, > `scalar`, `numeric`, etc. > > I look forward to your feedback, and especially with your > experimentation with the implementation. > > Levi Morrison > > [1]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > [2]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples > [3]: > https://github.com/php/php-src/compare/master...morrisonlevi:variance2 > [4]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#future_scope > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- regards / pozdrawiam, -- Michał Brzuchalski about.me/brzuchal brzuchalski.com

Benjamin Morel

7 years ago
I can only say that I've been waiting for this feature for years and am really looking forward to see it implemented, hopefully in 7.4. Good job on the RFC, I wish you luck! On Mon, 26 Nov 2018 at 22:26, Levi Morrison <levim@php.net> wrote:

Larry Garfield

7 years ago
On Monday, November 26, 2018 3:25:52 PM CST Levi Morrison wrote:
> I am happy to announce my latest RFC, [Covariant Returns and > Contravariant Parameters][1], is open for discussion. If you do not > recognize those terms then hopefully the introduction coupled with the > [examples][2] will help. Here is one snippet that demonstrates > covariant return types: > > <?php > interface Repository { > function fetch(int $id): ?Entity; > } > > class UserFactory implements Repository { > function fetch(int $id): ?UserEntity { > /* Since UserEntity is an Entity, this is now allowed */ > /* ... implementation ... */ > } > } > ?> > > Covariant return types and contravariant parameter types are highly > requested features; here are a few of the bug reports: > > * https://bugs.php.net/bug.php?id=71825 > * https://bugs.php.net/bug.php?id=72442 > * https://bugs.php.net/bug.php?id=75385 > * https://bugs.php.net/bug.php?id=75823 > > There is a [preliminary implementation][3] that is available. It will > not be rebased during discussion to allow people to check out the code > and get updates without worrying about it breaking. The code quality > can definitely be improved, and there are still a few todo comments in > the code. > > Please do not discuss the items found in [Future Scope][4] as part of > this thread, which includes discussing types such as `mixed`, > `scalar`, `numeric`, etc. > > I look forward to your feedback, and especially with your > experimentation with the implementation. > > Levi Morrison > > [1]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > [2]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#exa > mples [3]: > https://github.com/php/php-src/compare/master...morrisonlevi:variance2 [4]: > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#fut > ure_scope
Looks like fun! Would this also include allowing a return type of `static`, which would be useful for the "Return the object that was invoked" case or "return a new instance of the same object" case? Currently we're limited to `return self`, which is, of course, not the same thing and less flexible. --Larry Garfield

Levi Morrison

7 years ago
On Tue, Nov 27, 2018 at 11:36 AM Larry Garfield <larry@garfieldtech.com> wrote:
> > On Monday, November 26, 2018 3:25:52 PM CST Levi Morrison wrote: > > I am happy to announce my latest RFC, [Covariant Returns and > > Contravariant Parameters][1], is open for discussion. If you do not > > recognize those terms then hopefully the introduction coupled with the > > [examples][2] will help. Here is one snippet that demonstrates > > covariant return types: > > > > <?php > > interface Repository { > > function fetch(int $id): ?Entity; > > } > > > > class UserFactory implements Repository { > > function fetch(int $id): ?UserEntity { > > /* Since UserEntity is an Entity, this is now allowed */ > > /* ... implementation ... */ > > } > > } > > ?> > > > > Covariant return types and contravariant parameter types are highly > > requested features; here are a few of the bug reports: > > > > * https://bugs.php.net/bug.php?id=71825 > > * https://bugs.php.net/bug.php?id=72442 > > * https://bugs.php.net/bug.php?id=75385 > > * https://bugs.php.net/bug.php?id=75823 > > > > There is a [preliminary implementation][3] that is available. It will > > not be rebased during discussion to allow people to check out the code > > and get updates without worrying about it breaking. The code quality > > can definitely be improved, and there are still a few todo comments in > > the code. > > > > Please do not discuss the items found in [Future Scope][4] as part of > > this thread, which includes discussing types such as `mixed`, > > `scalar`, `numeric`, etc. > > > > I look forward to your feedback, and especially with your > > experimentation with the implementation. > > > > Levi Morrison > > > > [1]: > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > > [2]: > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#exa > > mples [3]: > > https://github.com/php/php-src/compare/master...morrisonlevi:variance2 [4]: > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#fut > > ure_scope > > Looks like fun! > > Would this also include allowing a return type of `static`, which would be > useful for the "Return the object that was invoked" case or "return a new > instance of the same object" case? Currently we're limited to `return self`, > which is, of course, not the same thing and less flexible. > > --Larry Garfield
It does not. To be honest, I did not think of it until your question.

Marcos Passos

7 years ago
Supporting `static` return would come in handy to define interfaces for immutable objects. Em ter, 27 de nov de 2018 às 19:01, Levi Morrison <levim@php.net> escreveu:

Levi Morrison

7 years ago
On Tue, Nov 27, 2018 at 2:00 PM Levi Morrison <levim@php.net> wrote:
> > On Tue, Nov 27, 2018 at 11:36 AM Larry Garfield <larry@garfieldtech.com> wrote: > > > > On Monday, November 26, 2018 3:25:52 PM CST Levi Morrison wrote: > > > I am happy to announce my latest RFC, [Covariant Returns and > > > Contravariant Parameters][1], is open for discussion. If you do not > > > recognize those terms then hopefully the introduction coupled with the > > > [examples][2] will help. Here is one snippet that demonstrates > > > covariant return types: > > > > > > <?php > > > interface Repository { > > > function fetch(int $id): ?Entity; > > > } > > > > > > class UserFactory implements Repository { > > > function fetch(int $id): ?UserEntity { > > > /* Since UserEntity is an Entity, this is now allowed */ > > > /* ... implementation ... */ > > > } > > > } > > > ?> > > > > > > Covariant return types and contravariant parameter types are highly > > > requested features; here are a few of the bug reports: > > > > > > * https://bugs.php.net/bug.php?id=71825 > > > * https://bugs.php.net/bug.php?id=72442 > > > * https://bugs.php.net/bug.php?id=75385 > > > * https://bugs.php.net/bug.php?id=75823 > > > > > > There is a [preliminary implementation][3] that is available. It will > > > not be rebased during discussion to allow people to check out the code > > > and get updates without worrying about it breaking. The code quality > > > can definitely be improved, and there are still a few todo comments in > > > the code. > > > > > > Please do not discuss the items found in [Future Scope][4] as part of > > > this thread, which includes discussing types such as `mixed`, > > > `scalar`, `numeric`, etc. > > > > > > I look forward to your feedback, and especially with your > > > experimentation with the implementation. > > > > > > Levi Morrison > > > > > > [1]: > > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > > > [2]: > > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#exa > > > mples [3]: > > > https://github.com/php/php-src/compare/master...morrisonlevi:variance2 [4]: > > > https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#fut > > > ure_scope > > > > Looks like fun! > > > > Would this also include allowing a return type of `static`, which would be > > useful for the "Return the object that was invoked" case or "return a new > > instance of the same object" case? Currently we're limited to `return self`, > > which is, of course, not the same thing and less flexible. > > > > --Larry Garfield > > It does not. To be honest, I did not think of it until your question.
After thinking about it, I believe it is out of scope for this RFC. While `static` would be covariant, it's also more than that. Accordingly, it deserves to have its own consideration and voting.

Larry Garfield

7 years ago
On Tuesday, November 27, 2018 3:00:27 PM CST Levi Morrison wrote:
> On Tue, Nov 27, 2018 at 11:36 AM Larry Garfield <larry@garfieldtech.com>
wrote:
> > Looks like fun! > > > > Would this also include allowing a return type of `static`, which would be > > useful for the "Return the object that was invoked" case or "return a new > > instance of the same object" case? Currently we're limited to `return > > self`, which is, of course, not the same thing and less flexible. > > > > --Larry Garfield > > It does not. To be honest, I did not think of it until your question.
On Tuesday, November 27, 2018 3:04:30 PM CST Marcos Passos wrote:
> Supporting `static` return would come in handy to define interfaces for > immutable objects.
Exactly the sort of use case I was thinking of. Or for builder objects, where you mutate the object in place and then return it. That's a common pattern, but return self and subclasses don't play that nicely there. Levi, is that something that could be reasonably added to this RFC or is that Hard(tm), like scalar/callable/etc? (I don't know that a static/self parameter declaration is even a thing, so it probably doesn't matter there; it does matter for returns, though.) --Larry Garfield

Dan Ackroyd

7 years ago
Marcos Passos wrote:
> Supporting `static` return would come in handy to define interfaces for > immutable objects.
But it's not a requirement, right? With this RFC, the following code will work: class ParentImmutable { function modify() : ParentImmutable { ... } } class ChidImmutable extends ParentImmutable { function modify() : ChidImmutable { ... } } Why should the RFC be expanded in scope to enforcing that child classes use more specific types? On Tue, 27 Nov 2018 at 21:16, Larry Garfield <larry@garfieldtech.com> wrote:
> Levi, is that something that could be reasonably added to this RFC > I don't know that a static/self parameter declaration is even a thing
Currently, static, self and parent are really more syntactic sugar that only apply in specific contexts, rather than actual types. This is a great source of sadness when it comes to their use in 'callable': https://wiki.php.net/rfc/consistent_callables . If I (or some other brave soul) finds enough fortitude to pickup that RFC, their use in the language might decrease. But more importantly, expanding the RFC from 'allowing variance to happen' to 'enforcing that child classes use variance' seems quite a big step, and would really need a separate strong rational of why it is needed, and why the added complexity is a good trade-off when it doesn't seem to be required for the use-case that it is being suggested for. It definitely needs a stronger argument for it, other than just saying it would be possible. cheers Dan Ack

Levi Morrison

7 years ago
On Mon, Nov 26, 2018 at 2:25 PM Levi Morrison <levim@php.net> wrote:
> > I am happy to announce my latest RFC, [Covariant Returns and > Contravariant Parameters][1], is open for discussion. If you do not > recognize those terms then hopefully the introduction coupled with the > [examples][2] will help. Here is one snippet that demonstrates > covariant return types: > > <?php > interface Repository { > function fetch(int $id): ?Entity; > } > > class UserFactory implements Repository { > function fetch(int $id): ?UserEntity { > /* Since UserEntity is an Entity, this is now allowed */ > /* ... implementation ... */ > } > } > ?> > > Covariant return types and contravariant parameter types are highly > requested features; here are a few of the bug reports: > > * https://bugs.php.net/bug.php?id=71825 > * https://bugs.php.net/bug.php?id=72442 > * https://bugs.php.net/bug.php?id=75385 > * https://bugs.php.net/bug.php?id=75823 > > There is a [preliminary implementation][3] that is available. It will > not be rebased during discussion to allow people to check out the code > and get updates without worrying about it breaking. The code quality > can definitely be improved, and there are still a few todo comments in > the code. > > Please do not discuss the items found in [Future Scope][4] as part of > this thread, which includes discussing types such as `mixed`, > `scalar`, `numeric`, etc. > > I look forward to your feedback, and especially with your > experimentation with the implementation. > > Levi Morrison > > [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples > [3]: https://github.com/php/php-src/compare/master...morrisonlevi:variance2 > [4]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#future_scope
Our existing engine doesn't always resolve "parent" at compile time when possible. As part of this patch "parent" is resolved at compile-time when possible and warnings and/or errors are emitted in certain cases where there were none before. For instance, this would only cause an error only if the method `C::m` were to be used: <?php class C { static function m(parent $m) {} } ?> This now emits an E_DEPRECATED warning when C is compiled. In 8.0 this should be elevated to a COMPILE_ERROR. The current edition of the RFC fails to mention this.

Levi Morrison

7 years ago
On Mon, Nov 26, 2018 at 2:25 PM Levi Morrison <levim@php.net> wrote:
> > I am happy to announce my latest RFC, [Covariant Returns and > Contravariant Parameters][1], is open for discussion. If you do not > recognize those terms then hopefully the introduction coupled with the > [examples][2] will help. Here is one snippet that demonstrates > covariant return types: > > <?php > interface Repository { > function fetch(int $id): ?Entity; > } > > class UserFactory implements Repository { > function fetch(int $id): ?UserEntity { > /* Since UserEntity is an Entity, this is now allowed */ > /* ... implementation ... */ > } > } > ?> > > Covariant return types and contravariant parameter types are highly > requested features; here are a few of the bug reports: > > * https://bugs.php.net/bug.php?id=71825 > * https://bugs.php.net/bug.php?id=72442 > * https://bugs.php.net/bug.php?id=75385 > * https://bugs.php.net/bug.php?id=75823 > > There is a [preliminary implementation][3] that is available. It will > not be rebased during discussion to allow people to check out the code > and get updates without worrying about it breaking. The code quality > can definitely be improved, and there are still a few todo comments in > the code. > > Please do not discuss the items found in [Future Scope][4] as part of > this thread, which includes discussing types such as `mixed`, > `scalar`, `numeric`, etc. > > I look forward to your feedback, and especially with your > experimentation with the implementation. > > Levi Morrison > > [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples > [3]: https://github.com/php/php-src/compare/master...morrisonlevi:variance2 > [4]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#future_scope
It has been two weeks now. If you want to provide any feedback, or follow-up on anything from the discussion, please do so soon. I hope to put this to vote before the end of the year.

Christoph Becker

7 years ago
On 11.12.2018 at 21:34, Levi Morrison wrote:
> On Mon, Nov 26, 2018 at 2:25 PM Levi Morrison <levim@php.net> wrote: > >> I am happy to announce my latest RFC, [Covariant Returns and >> Contravariant Parameters][1], is open for discussion. If you do not >> recognize those terms then hopefully the introduction coupled with the >> [examples][2] will help. […] >> >> [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters >> [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples > > It has been two weeks now. If you want to provide any feedback, or > follow-up on anything from the discussion, please do so soon. I hope > to put this to vote before the end of the year.
Thanks for working on this, Levi. Highly appreciated! I may have missed this, but otherwise I'd be quite surprised that nobody had commented on: | Therefore, by-reference parameters are still contravariant, […] Call-by-reference is not seldom used to provide out-parameters, but these should not be contravariant according to LSP. Therefore, it might be best to keep by-reference parameters invariant.
-- Christoph M. Becker

Levi Morrison

7 years ago
On Wed, Dec 12, 2018 at 4:25 AM Christoph M. Becker <cmbecker69@gmx.de> wrote:
> > On 11.12.2018 at 21:34, Levi Morrison wrote: > > > On Mon, Nov 26, 2018 at 2:25 PM Levi Morrison <levim@php.net> wrote: > > > >> I am happy to announce my latest RFC, [Covariant Returns and > >> Contravariant Parameters][1], is open for discussion. If you do not > >> recognize those terms then hopefully the introduction coupled with the > >> [examples][2] will help. […] > >> > >> [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters > >> [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples > > > > It has been two weeks now. If you want to provide any feedback, or > > follow-up on anything from the discussion, please do so soon. I hope > > to put this to vote before the end of the year. > > Thanks for working on this, Levi. Highly appreciated! > > I may have missed this, but otherwise I'd be quite surprised that nobody > had commented on: > > | Therefore, by-reference parameters are still contravariant, […] > > Call-by-reference is not seldom used to provide out-parameters, but > these should not be contravariant according to LSP. Therefore, it might > be best to keep by-reference parameters invariant. > > -- > Christoph M. Becker
Christoph, we cannot make any guarantees about the type of the variable when the function returns because the type of the parameter is only checked on function entry, and not also on function exit, e.g. function array_baz(array &$in) { $in = 1; } $array = []; array_baz($array); // valid var_export($array); // 1 I do think we ought to have "out" parameters some day which would prevent this behavior (as well as have some other benefits), but that is out of scope for this RFC. The RFC notes that if we had "inout" parameters that they would need to be invariant. It also says that "out" parameters would be invariant, but they may be covariant depending on the exact semantics specified -- all that can be handled in the RFC that proposes it. I will add this example (or maybe a better one) to the RFC. Thanks for bringing it up.

Christoph Becker

7 years ago
On 12.12.2018 at 17:28, Levi Morrison wrote:
> On Wed, Dec 12, 2018 at 4:25 AM Christoph M. Becker <cmbecker69@gmx.de> wrote: >> >> On 11.12.2018 at 21:34, Levi Morrison wrote: >> >>> On Mon, Nov 26, 2018 at 2:25 PM Levi Morrison <levim@php.net> wrote: >>> >>>> I am happy to announce my latest RFC, [Covariant Returns and >>>> Contravariant Parameters][1], is open for discussion. If you do not >>>> recognize those terms then hopefully the introduction coupled with the >>>> [examples][2] will help. […] >>>> >>>> [1]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters >>>> [2]: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters#examples >>> >>> It has been two weeks now. If you want to provide any feedback, or >>> follow-up on anything from the discussion, please do so soon. I hope >>> to put this to vote before the end of the year. >> >> Thanks for working on this, Levi. Highly appreciated! >> >> I may have missed this, but otherwise I'd be quite surprised that nobody >> had commented on: >> >> | Therefore, by-reference parameters are still contravariant, […] >> >> Call-by-reference is not seldom used to provide out-parameters, but >> these should not be contravariant according to LSP. Therefore, it might >> be best to keep by-reference parameters invariant. > > Christoph, we cannot make any guarantees about the type of the > variable when the function returns because the type of the parameter > is only checked on function entry, and not also on function exit, e.g. > > function array_baz(array &$in) { > $in = 1; > } > $array = []; > array_baz($array); // valid > var_export($array); // 1 > > I do think we ought to have "out" parameters some day which would > prevent this behavior (as well as have some other benefits), but that > is out of scope for this RFC. The RFC notes that if we had "inout" > parameters that they would need to be invariant. It also says that > "out" parameters would be invariant, but they may be covariant > depending on the exact semantics specified -- all that can be handled > in the RFC that proposes it.
I was not aware of this – thanks for the explanation. In my opinion, yet another good reason to avoid references.
> I will add this example (or maybe a better one) to the RFC. Thanks for > bringing it up.
Thanks. Also documented now: <http://svn.php.net/viewvc?view=revision&revision=346309>.
-- Christoph M. Becker