On Mon, Jun 15, 2026 at 12:28 PM Rob Landers <[email protected]> wrote:
>
>
>
> On Mon, Jun 15, 2026, at 20:22, Matthew Brown wrote:
>
> On Mon, 15 Jun 2026 at 12:28, Levi Morrison <[email protected]> 
> 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;
>         }
>     }

The version with a lower bound says it returns an A or an ancestor of A.
The version with the union type says it returns an A or a B, and
there's no relation between A and B at all.

They both allow correct code: you can correctly return an A or
ancestor of A in either one. Only the version with the lower bound
rejects incorrect code, though, and that's an important duty.

But this is tangential to my main point: if we accept that we are
moving towards fully reified generics, and this is only a stepping
stone, and we document this widely and educate about it, then in
future versions we can tighten from "bounds erased" to "fully
reified." Yes, there will still be breakages, but far, far fewer
breakages. This should be tolerable.

I don't want this RFC to be our final form: I only want it to be a
stepping stone.

Reply via email to