PHP's most serious generics proposal yet got voted down 7-19 — here's what it would have looked like
PHP has flirted with generics before and walked away every time. The 2016 reified-generics RFC never even made it to a vote. This year's attempt, the Bound-Erased Generic Types RFC, was different — it had a working implementation (php-src PR #21969) behind it before voting opened, which is usually a sign an RFC is taken seriously. It still lost, 7 Yes to 19 No with 10 Abstain, well short of the two-thirds majority PHP requires for a language change. The vote ran 14–28 June 2026. I wanted to understand what was actually on the table, because "PHP almost got generics" undersells how concrete this proposal was.
What it would have looked like
The syntax was erasure-based — compile-time only, no runtime type enforcement of the parameter itself, which is a specific and important design choice I'll come back to. Classes, interfaces, traits, functions, methods, and closures could declare type parameters:
final readonly class Pair<+L, +R> {
public function __construct(public L $left, public R $right) {}
}
class Sortable<T : Comparable<T>> {} // bounded, recursive
class Cache<K = string, V = mixed> {} // default type args
Instantiating with an explicit type argument used turbofish syntax: $user = new Box::<User>($user);. At runtime, each type parameter would be erased to its bound (or mixed if unbounded) — so Box<int> and Box<string> would genuinely be the same class underneath, with the compile-time, link-time, and runtime enforcement the RFC describes operating on that erased view, not on the original type argument.
Why it lost
The RFC's own text doesn't record a single dominant objection, but the discussion thread objection I found most convincing — raised by voters including Rowan Tommins — is that native syntax with no runtime enforcement of the actual type argument is, in practical terms, a step backward from what static analysis tooling already does. PHPStan and Psalm already express generics through @template PHPDoc annotations, and they check them with more precision than an erased runtime type could ever report back to you in a stack trace. Shipping language syntax that's weaker than the docblock convention it would partially replace is a real argument, and apparently a majority of voters agreed with some version of it.
The one piece of the RFC that did land: a secondary vote on variance-marker syntax, rendered moot by the primary RFC failing, but settled anyway — in T / out T (the C#/Kotlin style) beat +T / -T (the Hack/Scala style) 24 to 2. If generics syntax comes back as a future RFC, that's presumably the direction it reaches for, since the vote wasn't close.
What this means if you're writing Drupal or Symfony code today
Nothing changes, which is itself the point. Drupal and Symfony code that wants generic-shaped collections or type-safe wrappers already leans on PHPDoc @template annotations checked by PHPStan, and this RFC's failure is a reasonably strong signal that's going to stay the pattern for a while — not a stopgap waiting on native syntax, but the actual mechanism PHP's own RFC voters implicitly endorsed by rejecting the alternative. I don't think that's a bad place to land. A docblock-driven type system that your IDE and CI already check is less exciting to write about than native syntax, but it's hard to argue it's worse than erased generics with no runtime teeth.