Re: [RFC] [Discussion] Bound-Erased Generic Types

From: Date: Tue, 09 Jun 2026 14:34:00 +0000
Subject: Re: [RFC] [Discussion] Bound-Erased Generic Types
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-131188@lists.php.net to get a copy of this message
On 9 June 2026 08:26:12 BST, Brent Roose <brent.roose@jetbrains.com> 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]

« previous php.internals (#131188) next »