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

From: Date: Sun, 17 May 2026 22:29:13 +0000
Subject: Re: [RFC] [Discussion] Bound-Erased Generic Types
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-130930@lists.php.net to get a copy of this message
On 16 May 2026 22:32:30 BST, Seifeddine Gmati <azjezz@carthage.software> wrote:
Hi Rowan, The parts this RFC enforces (generic declaration syntax, type-parameter resolution, inheritance arity, bound conformance, parametric LSP, variance soundness, and turbofish arity) are exactly where static analysis tools currently disagree most.
Thanks. It sounds like there's a few different things: Some differences are directly resolved by the proposal; most notably, everything around syntax and keyword naming, since this would be fully standardised in PHP. In some cases, the problem remains, but the RFC gives the *user* power to remove the ambiguity; e.g. inference has no one right answer, and explicit call-site syntax means users don't have to rely as much on how tools approach it. I can see why that is hard to do without new and concise syntax. In other cases, it sounds like the correct answer is actually an established fact of type theory - e.g. the behaviour of covariance and diamond inheritance. In those cases, the value of the RFC is more subtle, because all it's doing is lending extra urgency to fixing something that everyone should agree is a bug.
Regarding your suggestion to include all unchecked type information in one place: adding a syntactic tier that PHP parses but ignores would be a new architectural pattern.
That is exactly my concern with your proposal! Behind the jargon, I think the long list of things enforced and not enforced boils down to: - the minimum bound of a type parameter is propagated automatically as the run-time type - the behaviour of extending a generic class or implementing a generic interface is enforced - the behaviour of passing a value to a generic function parameter, return type, etc, is completely unenforced; the language just provides syntax for SA tools to hang their own semantics onto In many cases, none of the enforced parts actually apply, so this: function<T> wrap(T $item): SomeDataStructure<T> would be entirely equivalent, as far as PHP is concerned, to this: function wrap($item): SomeDataStructure All of the rest is just "a syntactic tier that PHP parses but ignores".
Beyond that, it creates its own coordination problem. If ~~lowercase-string is parsed by PHP but interpreted by tools,
any disagreement on semantics (e.g., whether "" is lowercase, whether the
rule is ASCII or multibyte, whether numeric strings count) remains. PHP would host syntax it doesn't understand, and the ecosystem would still lack
a governance mechanism for those semantics. making it truly 100% useless.
If the implementation was actually enforced by PHP, it would not use the extra syntax. If the implementation was *not* enforced by PHP, tools would have to choose how to implement it; either individually, or through collective decision-making between tools. It would make no difference whether PHP spelled the type as "lowercase-string" or "string~~lowercase". The biggest advantage I see is the speed of innovation - I've seen ideas for new pseudo-types floated on this list, or on social media, and an implementation available in tools within days or weeks. Users can then start using it immediately. A full implementation in the core language would wait for the next annual release; and then for users to reach that level as their minimum supported. I thought tools might welcome a way to move away from docblock-parsing without giving up that ability to innovate new features.
On the visibility of type parameters like TNode: it's true they can look like concrete types at use sites. However, this is consistent with languages like Java, Rust, and TypeScript. Conventions like single uppercase letters or PascalCase (e.g. TKey, TNode) are already well-established in the PHP ecosystem through @template. Native syntax promotes these established signals into the language.
I wasn't making any comment about how type parameters are spelled. I was responding specifically to this sentence in your previous e-mail:
But the same argument applies to <...>: anything in angle brackets is the generic type layer, anything outside is the runtime-checked layer.
I was simply pointing out that some things in the "generic type layer" are not marked by angle brackets, so in the syntax proposed by the RFC, there is no visual signal that these are unenforced types. Regards, -- Rowan Tommins [IMSoP]

« previous php.internals (#130930) next »