On 13/05/2026 21:08, Seifeddine Gmati wrote:
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.
You're probably right on raw counts. But scalar types and generics
aren't the same kind of feature


It was your choice of comparison, not mine.


The audience for generics is "anyone who wants the type relationship
between two uses of `T` to be enforced."


The audience for generics includes both people *writing* generic classes and interfaces, and people *consuming* those classes and interfaces.

Take the Laravel/Eloquent Collections example mentioned in the RFC. It didn't take me long to find this example in the documentation at https://laravel.com/docs/13.x/eloquent#chunking-results

Flight::where('departed', true)
    ->chunkById(200, function (Collection $flights) {
        $flights->each->update(['departed' => false]);
    }, column: 'id');

Note that the callback is declared with a typed parameter of Collection. As soon as the language allowed it, it would be natural to instead use the generic form:

Flight::where('departed', true)
    ->chunkById(200, function (Collection<Flight> $flights) {
        $flights->each->update(['departed' => false]);
    }, column: 'id');

A novice user might at first be confused by the meaning, but a 5 minute introduction will tell them that this means the function accepts specifically a "Collection of Flight objects". So now, they can use it in their own code - instead of "function getLoggedInUsers(): Collection", they'll write "function getLoggedInUsers(): Collection<User>".

They might not ever learn how to declare their own generic class, and certainly not what "covariance", "bound-on-bound", and "parametric LSP" mean. Crucially, they won't know what "erased generics", "monomorphized generics" and "reified generics" mean, and why a language might include one or another.

What they will know is that if they return something other than a Collection object, PHP will give an error. Their natural assumption will be that returning a Collection of something other than User objects will also error.


So, how can we help that novice user?

Can we change the syntax slightly, to make a clearer distinction between the enforced and unenforced parts of the type?

Can we introduce the feature in such a way that you can't use it without also running some kind of type checker?



The bar for shipping a feature can't be "no new user will ever misuse it," 
because
no PHP feature meets that bar.


That's not what I was saying at all. I was saying we have to include those new users as part of the audience for the feature, in contrast to your repeated claims that the audience is entirely made up of people who already use SA tools.


PHP ships `#[Attribute]`, `#[Override]`, `#[Deprecated]`,
`#[SensitiveParameter]`, `#[AllowDynamicProperties]`,
`#[ReturnTypeWillChange]`, `#[NoDiscard]`, And more. and these have
specific semantics, not abstract extension. PHP also ships interfaces
with no enforced behavior beyond a method contract: `Iterator`,
`Countable`, `Stringable`, `ArrayAccess`.


Every single one of those has behaviour implemented in PHP. Iterator is used by foreach(), Countable by count(), and so on. You can use them all, out of the box, and they *do something*.

The closest examples I can think of are the SplObserver and SplSubject interfaces, which really don't do anything. If they were proposed now, I don't think they'd be included; that kind of standardisation is left to userland orgs like PHP-FIG. They're useless, but harmless. They don't reserve any unique syntax, just a couple of class names; they don't look like they're going to do something then not do it.


It's the same split that already governs how PHP
validates everything from array element types to callable signatures.


The difference is that right now, you can look at some code and see, very clearly, which types are being enforced by PHP, and which are just annotations for use by external tooling.

It's a matter of opinion whether native syntax for unenforced types would be a good or bad thing, but it's an undeniable fact that it would be a *new* thing.


--
Rowan Tommins
[IMSoP]

Reply via email to