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