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;
        }
    }

Hack also has `super` type constraints:
https://hhvm.com/blog/9215/covariance-contravariance-and-super-type-constraints

Reply via email to