Hi Rowan,

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

You're right that I overstated this, PHPStan verifies many docblock
annotations at low levels, not just at level 9. The claim narrows
correctly for *generic* annotations specifically: `@template`,
`@template-extends`, `@implements`-with-generic-args, and the
parametric relationships they introduce. Those tend to live at higher
levels because PHPStan has no native syntax to cross-reference
against, so the checks must make assumptions about user intent that
warrant a higher confidence threshold.

The shift after this RFC is exactly that cross-reference: once `class
Box<T : object>` is in syntax, the arity, bound, and inheritance
checks are language-level violations that any tool reports at any
level. Ondřej confirmed that PHPStan will promote generic violations
to baseline checks once they're native. Mago already has them as
baseline errors (we don't have levels). I'm not certain about Psalm,
but I'd be surprised if Daniil disagreed.

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

Both paths exist in every SA tool. Parsers handle the project source.
Reflection handles classes for which the tool doesn't have source
(e.g., built-ins, extensions). Psalm has explicit Reflection-based
class registration:
https://github.com/vimeo/psalm/blob/6ff4aa2b472a5a4dd16a75c807da633d2c2e9368/src/Psalm/Internal/Codebase/Reflection.php#L57

Mago and PHPStan have equivalent layers. The RFC's Reflection API
serves the second path; tool parsers continue to serve the first. Both
paths need updating to use native generic syntax. That work is real,
and the maintainers above have committed to doing it once the RFC
lands.

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

This has been tried. JetBrains explicitly attempted to bring the SA
tool maintainers together around 2020 to produce a conformance spec
for docblock generics; Brent referenced it in his email on this list.
The attempt failed. The reason is structural: docblock generic syntax
has no governance mechanism, no shared standard to anchor to, no
enforcement path (a tool that ignores the spec faces no consequences),
and the tools have already diverged on edge cases that would require
breaking changes to reconcile. Tag aliases differ (`@extends` vs
`@template-extends`), bound resolution differs, variance support
differs.

The only governance body that the ecosystem actually treats as
authoritative is internals. That's the structural fact behind this
RFC: not just "syntax in PHP is intrinsically better than syntax in
docblocks" (which is true), but "the standardisation step that would
make docblock generics consistent across tools requires authority no
party in the ecosystem currently has."

> 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. [...] Straw man example: class Foo ~~Foo<T> extends 
> Bar ~~Bar<int,T>

The visual-distinction argument cuts both ways too. You're arguing
that `~~` makes the SA-checked layer visible to the reader. But the
same argument applies to `<...>`: anything in angle brackets is the
generic type layer, anything outside is the runtime-checked layer.
Once the convention is established (which TypeScript, Hack, Kotlin,
Scala, Swift, C++, Java, and C# have already established), the
distinction is just as visible as a `~~` prefix would be, without
adding a new syntactic primitive PHP doesn't have anywhere else.

Cheers,
Seifeddine.

Reply via email to