Hi Rob,

> Tested on your PR branch [...] But the entry-side check accepts the
string, contradicting the same sentence's claim that those checks read
substituted parameter types.

Good find. That's a bug in the implementation. I'll fix it before the RFC
moves to voting.

> I'm a bit confused. In your earlier email you said that tools currently
can't converge on simple generics correctness [...] but say that this will
force them to converge.

The convergence claim is about what happens once the language defines a
specific semantics, not about tools agreeing on their own. Today, tools
disagree because each tool must invent a semantics for docblock generics,
and the invented semantics differ. Once PHP defines the diamond-merge rule
(or any other semantic the engine enforces), tools have a single
specification to conform to. The convergence isn't "tools deciding to
agree"; it's "tools matching the language's behavior, the same way they
match the language's behavior for scalar types, union types, intersection
types, and every other type-system feature that shipped through this same
process."

The Mago bug is evidence for the convergence claim, not against it. The bug
exists because there was no authoritative specification for the behavior;
Mago, PHPStan, and Psalm each made different choices. Under the RFC, there
is one specification (link-time diamond merge produces the parameter-union,
return-intersection signature), and tools will conform to it because the
language enforces it.

> Box<A&B>'s internal value flow is observationally identical to
Box<A|B>'s, or Box<mixed>'s -- all accept and produce values satisfying the
bound. The static subtyping relationship is real and enforced at link-time
parametric LSP. It's invisible at runtime.

Correct, and this is the trade bound erasure makes. The engine enforces the
bound; the parametric refinement is enforced at the SA layer. It's the same
trade-off already in effect for every `@template` annotation in production
PHP code today: the engine doesn't enforce the parametric relationship, the
SA tools do.

> What I don't see addressed anywhere is the new-user case: a developer
who's never seen generics encounters <T> in production code, writes their
own, runs it, gets no runtime feedback when their value-level intuition
diverges from the underlying expectations without using a tool.

For genuinely new developers, the path is the same as for every other
feature: documentation explains what generics do, the same way it explains
classes, inheritance, functions, types, and so on. Someone new won't be
familiar with every single feature of PHP *except* generics. Either:

1. They know OOP in general: meaning they have already encountered generics
in Java, Scala, Kotlin, C#, or a similar language (which uses type
erasure).
2. They're genuinely new to programming; generics are no harder than any
other feature they'll need to learn from documentation.

> 200k files is a drop in the bucket when you've worked on PHP repos
spanning millions of files.

I've worked on multi-million-line PHP codebases that used `@template` (or
native erased generics in HackLang) extensively and strictly. The number is
a lower bound from public GitHub search, not a ceiling. Add private
codebases at Slack, Quizlet, Vimeo, and 100s of major companies running PHP
at scale, and the count grows significantly. The 200k figure is evidence of
widespread adoption, not the totality of it.

Cheers,
Seifeddine.

Reply via email to