On 9 June 2026 08:26:12 BST, Brent Roose <[email protected]> wrote:

>To reiterate what I've said before: generics aren't a runtime tool. 


Generics are as much a runtime tool - or as little - as any other type 
declaration. If it is useful to enforce "function foo(int $bar): int" at 
runtime, it is equally useful to enforce "function foo<T>(T $bar): T" at 
runtime.

A mode which erases all runtime checks which can be proven statically would be 
a valuable addition. Again, we're into "ship a native analyser" territory, 
though, because you have to know which types can be trusted, and which are 
still unchecked.

Importantly, you can't rely on static analysis outside of a closed system - a 
library can't choose to erase all types, and still make assumptions in code 
based on users not passing other types.

PHPStan has a specific setting to account for this:

> PHPStan by default doesn’t differentiate between PHPDoc and native types. It 
> considers them both as certain.
>
> This might not be what you want in case you’re writing a library whose users 
> might pass a wrong argument type to a function. Setting 
> treatPhpDocTypesAsCertain to false relaxes some of the rules around 
> type-checking.

Replace "PHPDoc" with "erased" and the statement applies to the current 
discussion. For example:

```
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');
    }
}
```

If the generic type can be trusted, then the is_int() check is redundant and 
can safely be removed. If generics are checked at runtime, it can be trusted; 
if the final running system has been successfully analysed and proven correct, 
it can be trusted. But analysing this code in isolation *can't* make it 
trusted; and analyzing the final running system may find cases which can't be 
proven until runtime.

As I understand it, the "partial erasure" approach, where the static analyser 
decides which runtime checks are needed, is used by Dart: 
https://dart.dev/language/type-system

Rowan Tommins
[IMSoP]

Reply via email to