Hi Rob, > This is a mischaracterization. To be more clear, the call itself approaches a > limit of 2x -- it isn't exactly 2x, and not all generic calls are always 2x. > I even gave real examples in my email showing real world generic heavy code > is only 30-50% slower. And this is without any real optimization work. This > is the ceiling, not a final result. Further, it appears to bear the same cost > as manually type checking the generics.
Real engineering, and the implementation is appreciated. But I disagree that "approaches 2x worst case, 30-50% on real generic-heavy code" reads as a small cost. Two reasons: 1. Generic-via-native isn't "use it OR keep using @template", once it ships, the docblock alternative goes away. Social pressure on every actively-maintained library is to migrate. Static-analysis tools will gradually downgrade or drop (eventually) their docblock-generic implementations once the native form is widely available (this is exactly what happened with attributes vs PHPDoc annotations after PHP 8.0). The cost isn't paid by libraries that opt into runtime-reified generics; rather, it's paid by every library that ships generics at all. Under either proposal, this is essentially every typed library that exposes a collection, iterable, repository, result type, or async primitive. 2. The cost compounds through the dependency graph, affecting even users who don't write generics themselves. Consider an application that never declares a generic of its own. It depends on Psl. Psl is generic end-to-end, covering collections, iterables, results, and options. Application code calling `Psl\Vec\map($vec, $fn)` pays the reified-check cost on every call, transitively, even though the application never wrote <...>. Now a concrete tooling case: [roave/BackwardCompatibilityCheck](https://github.com/Roave/BackwardCompatibilityCheck) runs as a CI step. It uses its own generics. It depends on Psl. The honest benchmark isn't "how much slower is one Psl\Vec\map call?", it's "how much longer does BackwardCompatibilityCheck take to run on a full codebase once Psl ships native generics and BCC adopts them?"If the answer is 4 minutes -> 6 minutes per CI run, multiplied across every PR in every project that uses BCC, that means slower CI, more compute spend, and longer feedback loops for everyone downstream. The "30-50% on generic-heavy code" framing also collapses once a user can't tell which of their dependencies count as "generic-heavy." Under this RFC, the cost question is "does your code use generics?", zero if no, small if yes (the substituted-contract checks I just landed sit at ±0.1% benchmark noise). Under universal reification, the question becomes "do you, or anything in your transitive dependency graph, declare generic types?", and for an ecosystem where ORM repositories, collection libraries, async runtimes, HTTP middleware kits, and standard-library replacements all want generics, the honest answer is "yes, everywhere." This isn't an argument against reified generics in principle. It's an argument that the perf characterisation in the post understates how the cost will be felt in practice once the syntax is the way to do generics in PHP. I think the right path is to land this RFC (erased + substituted contract + reflection, zero cost for non-generic code, small cost for substituted check sites), let the ecosystem migrate from docblock to native, and then evaluate reified-via-opt-in on top of it. Your branch is then the natural starting point for that follow-up RFC, with much sharper data on what fraction of real PHP workloads actually carry generic types in their hot path. If that follow-up shows reified can land at a perf cost the ecosystem can absorb across the dependency-graph case, great. If it can't, we'll know, and the cost of finding that out will be much lower if the erased form is the baseline rather than the starting point. Cheers, Seifeddine
