On 15 May 2026 00:32:05 BST, Seifeddine Gmati <[email protected]> wrote:

>Generic type information currently lives in optional levels because it
>lives in optional syntax (docblocks).


This is, quite frankly, nonsense.

If you write a function with no native type information, but an "@return int" 
docblock, PHPStan will report an error for a missing return statement at Level 
0, and for an incorrect return statement on Level 3.

There's no relationship between the syntax needed and the types of analysis 
performed.


> That's the point: native syntax means the language
>did the work, and tools surface violations at whatever strictness the
>user already has configured.


As Daniil pointed out, SA tools analyse code with offline parsers, not by 
loading and reflecting it; so the native enforcement of arity etc will still 
need to be reimplemented in each tool.

The RFC will act as a standardisation of what tools *should* enforce around 
those things; but that could equally be done by agreeing a set of conformance 
tests based on the existing docblock syntax. In fact, those conformance tests 
would be needed whatever the syntax, if the goal is to eliminate different 
handling in different tools.


>The actual situation is that PHP has a runtime-checked layer (what the
>engine validates) and an SA-checked layer (what tools verify). The two
>layers complement each other. Native generics formalize a part of the
>SA-checked layer that the engine can partially absorb.


I can agree with this framing. I think where we differ is that you see unifying 
those layers in one syntax as a good thing, but I see it as a bad thing: I 
think it is useful to be able to look at the code, and understand which parts 
are definitely going to be enforced by the runtime-checked layer.

I think the ideal is to somehow create a standardised syntax for the SA-checked 
layer, but still keep it separate from the syntax for the runtime-checked 
layer. If neither docblocks nor attributes are a good basis for that, maybe 
there's some other primitive we can add so that users can mark both the 
"runtime type" and the "SA type". 

Straw man example: 

class Foo ~~Foo<T> extends Bar ~~Bar<int,T> {
   public function foo(string ~~non-empty-string $in): array ~~list<T> {
...


Maybe PHP would process the syntax, but not the semantics, of the extra type 
information; SA tools would then be free to invent new pseudotypes within that 
framework, without needing to wait for a full PHP release cycle every time. 



Rowan Tommins
[IMSoP]

Reply via email to