Re: [VOTE] [RFC] Bound-Erased Generic Types
| From: | Rob Landers | Date: | Mon, 15 Jun 2026 18:27:14 +0000 |
| Subject: | Re: [VOTE] [RFC] Bound-Erased Generic Types | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-131290@lists.php.net to get a copy of this message | ||
On Mon, Jun 15, 2026, at 20:22, Matthew Brown wrote:
> On Mon, 15 Jun 2026 at 12:28, Levi Morrison <levi.morrison@datadoghq.com> wrote:
>> > Voting is now open on the Bound-Erased Generic Types RFC, as announced
>> > in the Intent to Vote message earlier this week.
>> >
>> > The vote started on 2026-06-14 at 16:50 UTC and ends on 2026-06-28 at 17:00 UTC.
>> >
>> > RFC:
>> > https://wiki.php.net/rfc/bound_erased_generic_types
>> > Discussion thread:
>> > https://news-web.php.net/php.internals/130816
>> > Implementation:
>> > https://github.com/php/php-src/pull/21969
>>
>> To my own surprise, I am voting yes on this proposal.
>>
>> I still believe that refied generics should be the goal. To that end,
>> I think we should be able to merge this and in minor versions, fix
>> "soundness" and implementation holes as "bug" fixes on that route. If
>> internals can agree on this, and then the community can communicate
>> this through education, promotion, documentation, etc, then this RFC
>> is simply a useful stepping stone.
>>
>> This is based on my own experience playing with the RFC, which
>> included reporting 2 bugs in the implementation on the RFC. To be
>> honest, it's not too useful to me. I very quickly run up against some
>> limitation when trying to build useful things. Most notably, we need
>> to be able to define lower bounds (syntax pending, obviously):
>>
>> class Option<+A>
>> {
>> // B >: A means B is an ancestor of A
>> // Since all As are Bs, you can return the A here
>> function get_or_default<B >: A>(Option $option, B $default): B
>> {
>> return $option->has_some()
>> ? $option->get()
>> : $default;
>> }
>> // todo: the rest of the implementation
>> }
>>
>> You can't take
A $default and return
>> A because this violates the
>> variance laws: a covariant type A cannot be used in parameter
>> position. So alternatively you could solve this with `inout A
>> $default` or similar.
>
> Presumably this would work with the current proposal:
>
> class Option<+A> {
> public function getOrDefault<B>(B $default): A|B {
> return $this->hasSome() ? $this->get() : $default;
> }
> }
>
> Hack also has super type constraints:
> https://hhvm.com/blog/9215/covariance-contravariance-and-super-type-constraints
It wouldn’t actually do anything though…
— Rob