> 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: scalar types are useful in isolation
(a single `int` parameter benefits a single function), whereas generic
types are *relational*; `Box<T>` is useful because of the relationship
between the parameter `T` and the value flowing through it, and that
relationship can only be checked by something that tracks types across
call boundaries. The audience for scalar types is "anyone who wants
their function to fail loudly when called with the wrong type." The
audience for generics is "anyone who wants the type relationship
between two uses of `T` to be enforced." These are different
populations, and the second one corresponds tightly to people who
already run SA tools, because there is no other way to extract value
from generic type information.

> Of course they will, because it will suddenly be much more visible. [...] 
> People who see docblocks as "just documentation" will see frameworks and 
> libraries putting it in "actual types" and copy it into their own code.

This is true of every successful language feature. Attributes
attracted users who hadn't previously used `@deprecated` or `@Route`.
Readonly attracted users who hadn't previously used `final` setters.
Match attracted users who hadn't previously used switch. Some of those
users used the new feature wrong before learning it; that's normal
language adoption, not a failure mode unique to generics. The bar for
shipping a feature can't be "no new user will ever misuse it," because
no PHP feature meets that bar.

> Attributes are very explicitly an *abstract extension point* for tooling to 
> do what it wants with. PHP does not attempt to standardise their use [...] 
> That's not the same as what you're proposing.

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`. The language has
historically been willing to ship type-system constructs whose
validation depends on either the runtime or external tooling, not just
abstract slots for users to define.

Native generic syntax has a similar shape: PHP ships the syntax and
the validation it can perform (compile time, link time, and turbofish
runtime, all enumerated in the RFC), while the parametric-relationship
layer requiring cross-call analysis remains where it has always been:
in SA tools. It's the same split that already governs how PHP
validates everything from array element types to callable signatures.

> 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, ...

Correct, and this RFC doesn't claim to (see "What did not collapse"
under 
https://wiki.php.net/rfc/bound_erased_generic_types#migrating_from_docblock_generics).
PHP's type system has been growing piecewise for a decade, scalar
types in 7.0, void and nullable in 7.1, object in 7.2, union types in
8.0, intersection types in 8.1, DNF in 8.2, true/false/null types
throughout, and there's no version of PHP that ships them all at once.
`class-string<T>`, literal types, negated types, type aliases, and
similar are each their own RFC, and each can be added to the language
over time. The fact that this RFC doesn't ship all of them isn't an
argument against shipping any of them; it's an argument for proceeding
incrementally, which is how PHP's type system has always evolved.

Cheers,
Seifeddine.

Reply via email to