On 14/06/2026 16:53, Seifeddine Gmati wrote:
Voting is now open on the Bound-Erased Generic Types RFC, as announced
in the Intent to Vote message earlier this week.

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


It will come as no surprise to those who followed the discussion that I have voted "No".

For those who did not, my position in a nutshell is: I want PHP to have generic types; but I want to be able to trust those types. This RFC does not deliver that.

----

This is not a technical argument about "erased" vs "reified" vs "monomorphized"; it's more philosophical: if there's native syntax, there should be native enforcement of some kind.

There are several versions of this RFC I could have supported, for example:

- Separating out the parts which *are* enforced, at compile and link time, and leaving more to Future Scope - An official tool which proved types statically, then erased them at run-time - A new syntax for "untrusted" types, as a structured replacement to docblocks

In its current form, I think it would be a step backwards for the language's type system.

----

Currently, a reader seeing a native parameter, return, or property type can trust that it will be enforced.

Additional unenforced types can be included in docblock annotations, where human readers and tools can choose how much to trust them. For example, the author of a library may document that users *should* pass correct types, but still write defensive code for if they fail to do so.

As a quick example, in the below, the language *guarantees* that the is_int() check is redundant:

function foo(int $bar) {
       if ( ! is_int($bar) ) {
       throw new \TypeError('Expected an int');
    }
}

This RFC proposes to *remove that guarantee*, and use native syntax for unenforced types.

In the code below, the is_int() call will *not* be redundant, because the language will only guarantee a type of "int|string", despite the native syntax indicating more:

interface Foo<T: int|string> {
    public function bar(): T;
}

function test(Foo<int> $foo): void {
    $bar = $foo->bar();
    if ( ! is_int($bar) ) {
       throw new \TypeError('Expected an int');
    }
}

----

I would like to thank Seifeddine for the hard work, and although I hope this RFC is not accepted, I also hope that others build on its foundations to deliver much-needed generic types to the language.

Regards,

--
Rowan Tommins
[IMSoP]

Reply via email to