On Wed, May 13, 2026, at 12:58 PM, Rowan Tommins [IMSoP] wrote:
> On 13 May 2026 17:19:21 BST, Seifeddine Gmati <[email protected]>
> wrote:
>>> This is an assumption that a lot of your reasoning seems to be based on,
>>> and as I've said already, I think it's a false assumption.
>>
>>The PHP 7.0 type-declaration rollout is the closest empirical test.
>>Native scalar types shipped to a community that had been using PHPDoc
>>@param and @return annotations for years. They didn't suddenly create
>>a new population of developers who type their code, some popular
>>projects argued the new types were useless and refused to adopt them.
>>The audience that gained native syntax was the audience that had
>>already been typing their code. People who didn't see value in types
>>before PHP 7.0 mostly didn't see value after, either.
>
>
> I don't think this is true at all. Users were writing "array", and
> class/interface types, in their code for many years before PHP 7.0,
> *and having them natively enforced*. Most of those users had never
> heard of static analysers, but as soon as static types became
> available, using them was entirely natural.
>
> If you survey current code bases, I bet you a drink of your choice that
> you will find code bases with some use of scalar types outnumbering
> code bases which have been tested with a Static Analyser by an order of
> magnitude.
>
>
>
>>The same dynamic will apply here. People who don't care about generic
>>type information today won't suddenly care because PHP grew the
>>syntax. The audience that uses @template in docblocks is the audience
>>that will use native generics.
>
>
> Of course they will, because it will suddenly be much more visible.
> Every "what's new in PHP" blog post will describe the new syntax, and
> people will start playing with it. People who see docblocks as "just
> documentation" will see frameworks and libraries putting it in "actual
> types" and copy it into their own code.
>
> And this is a good thing! We *want* new language features to be
> interesting to more people. But we also want them to be *useful* to
> those people, not documented in the manual as "advanced users only; if
> you're the target audience for this, you probably don't need this page".
>
>
>
>>Attributes themselves are a counter-example. They shipped in PHP 8.0
>>specifically to formalize what frameworks had been doing in docblocks.
>
>
> Attributes are very explicitly an *abstract extension point* for
> tooling to do what it wants with. PHP does not attempt to standardise
> their use; it doesn't even validate that attribute names correspond to
> valid classes unless you ask it to. PHP provides some attributes out of
> the box, but only when it also includes some *behaviour* for those
> attributes.
>
> In the same way, PHP provides the ability to define interfaces. It also
> provides interfaces to interact with included features, like
> SessionHandlerInterface. But it leaves it up to the community to agree
> interfaces for things that are not included with the language, like
> LoggerInterface or CacheInterface.
>
> That's not the same as what you're proposing.
>
>
>>Beyond that, expressing generics through attributes specifically
>>doesn't work.
>
> Fair enough. My point stands though: the language should provide
> abstract extension points, or working implementations, not empty syntax.
I fully echo Rowan's comments. The assumption that the Venn diagram of "uses
generics" and "uses PHPstan/Psalm" is a circle is presented without compelling
evidence, and I don't believe it to the be case today. Even if it were the
case today, I am quite confident it would not remain so for long with this RFC.
Because this RFC is providing some validation (in practice, I think it is
providing most by number; it's just the turbofish that doesn't yell at you
natively), users will run into generics validation messages at some point (just
as they do any other syntax error). It will be confusing when some things
self-validate and others do not, especially when PHP itself starts shipping
stdlib code that uses generics.
Consider, if I read the RFC correctly this will (correctly) error at link time:
interface Foo<T: DateTimeInterface> {}
class Bar implements Foo<User> {}
So that part of the type system is enforced. It will therefore be natural for
users to expect that
new Baz<User>(new Product $p);
will error on them. I fully get the reasons why that's way harder to do than
the former. As I said, I could even be talked into accepting it for now, with
appropriate communication around it, as long as there is a clear path toward
enforcing it later. There's "enough" enforcement that it's not quite as bad as
Python...
And basically everyone who uses PHP is going to encounter generics sooner or
later. As I noted above, PHP *will* start shipping stdlib code that uses
generics. Gina's work on generics was specifically intended to aid her
previous work on Fetch API interfaces, to split ArrayAccess up into properly
atomic features. Those interfaces naturally benefit from being generic, and
would be implemented as such. So that means literally everyone who uses them
in the future would encounter generics, and in that case, it would be enforced
(at compile/link time) already. Similarly, if this passes, it will be about 4
seconds before I start working on Seq, Set, and Dict collection classes for
stdlib (longer if I have trouble finding a partner for it), and those would
unquestionably be generic. And that's just two obvious examples. Generics
would become as much a part of the standard vocabulary of PHP developers as
scalar types and interfaces. If they don't, then we've failed. :-)
But count me out for opt-in enforcement. We either enforce it or we don't.
The reason strict_types exists is, largely, the billion lines of pre-existing
code hat was effectively "loose" already, and people not wanting to have to
fight that. Let's not create another of those situations. If call-site
enforcement can be made cheap enough to include, it's cheap enough to *always*
include. If we want to add a "disable type checks in prod" flag, that would be
an ini-setting, not a code-level setting, and should be blanket for all types.
It's also a completely separate question from this RFC.
Which is why I previously suggested some sort of AOT first-party checker, as a
way to help ensure that whenever we do manage to add automatic enforcement,
it's a minor speed bump for existing code, not a massive pseudo-BC-break, like
warnings on undefined keys was.
> There's also the elephant in the room that the proposal doesn't remove
> the need for standardising a docblock or attribute approach anyway,
> because it is inevitably going to miss things the SA tools support:
> class-string<T>, array<int,Foo>, iterable<Bar>, non-empty-string, ...
>
> That again follows from it not being an abstract extension point like
> docblocks and attributes.
>
> Advanced users, who you say are the target audience, will still have to
> work with both syntaxes; and will still find differences between tools
> which aren't covered by the subset of validation that PHP has taken
> ownership of.
This is also a very valid point worth calling out. One of my more common usage
patterns today is the Doctrine ORM example in the RFC (with class-string<T>).
I'm still now sure how, or if, the RFC syntax would handle that case.
Is there even a viable future way to include such more-complex checks natively
in the future? For some, the answer is "add that feature to PHP, duh" (like
array<int, Foo>, or preferably Dict<int, Foo>), and I have some ideas for
non-empty-string that people probably won't like :-), but I'm not sure what to
do with class-string<T> or other more esoteric examples.
I really want to like this RFC, and I really want generics. This is likely the
most viable approach that's been put forward to date. But I am still very,
very nervous about the land-mines it lays in front of us if we're not careful.
--Larry Garfield