Le ven. 15 mai 2026 à 18:03, Larry Garfield <[email protected]> a
écrit :

>
> On Fri, May 15, 2026, at 7:09 AM, Nicolas Grekas wrote:
> > Hi all,
> >
> > Thanks Seifeddine for putting this together. This is an impressive
> > piece of work, and the general approach is sound to me. Looking forward
> > to where this discussion lands; I hope we'll reach enough consensus to
> > merge.
> >
> > Le ven. 15 mai 2026 à 13:13, Rowan Tommins [IMSoP]
> > <[email protected]> a écrit :
> >> 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'd like to put a syntax proposal on the table that may address Rowan's
> > concern, and that also addresses something I'm worried about
> > independently: the migration path for existing libraries.
> >
> > How does a library that uses @template docblocks today migrate to
> > native syntax without forcing a BC break on its consumers? Multiplied
> > across the libraries out there, this is a major point of tension for
> > the ecosystem we need to anticipate.
> > Existing @template annotations were adoptable gradually *because*
> > they're invisible to the engine.
> > Native <T> syntax, as the RFC proposes it, doesn't have that property:
> > a library cannot adopt it without bumping its minimum PHP version and
> > pulling all its consumers with it.
> >
> > We've solved this exact problem once before for attributes. The #[...]
> > syntax was deliberately designed so older PHP versions would parse it
> > as a # line comment, which is what made the adoption across the
> > ecosystem so smooth.
>
> Though recall that was an after-passage change; the original attribute
> syntax was << >>, which everyone apparently hated, so we changed it twice
> in rapid succession.  (I am very very glad we did switch to the
> Rust-inspired syntax, but just making sure the history is clear.)
>

It was, and part of the reason why the new syntax was way better is that it
was a comment to the older engine version.
Retrospectively, we can all testify how much this boosted if not just
permitted broad adoption.


>
> > The same trick is available for generics if we pick the right
> > delimiter. Concretely, write #<...> everywhere <...> appears in the
> > current RFC: declarations, inheritance clauses, type uses in
> > signatures, call-site arguments. One syntax, used uniformly.
> >
> > Three benefits, beyond the migration story:
> >
> > 1. FC for free. A library can adopt native generics in source today and
> > continue running on older PHP versions, because the engine just sees
> > comments. No need to coordinate with the min-PHP bump.
> > 2. The turbofish goes away. No need to disambiguate < from less-than
> > comparison. With #<...>, the token is unique and unambiguous
> > everywhere: at declaration, use, and call site. We get to drop a whole
> > grammar mechanism rather than introduce one.
> > 3. Rowan's concern is addressed typographically. Anything inside #<...>
> > is the erased, SA-enforced layer; everything outside follows the
> > engine's normal runtime-checked rules.
> >
> > For codebases that want to adopt native generics while still supporting
> > earlier PHP versions, #<...> would need to sit at the end of a line so
> > older parsers consume it as a # line comment. Code targeting only
> > generics-aware PHP can write it inline. The line-break constraint is a
> > transitional code-style cost, not a permanent property of the syntax,
> > and it's bounded by however long libraries support pre-generics
> > versions.
> >
> > WDYT? I expect Seifeddine has good reasons to prefer the current
> > syntax. I'd like to put this on the table because the FC story it
> > unlocks, combined with the turbofish simplification, might be worth the
> > trade-off and might help gather a broader consensus.
> >
> > Cheers,
> > Nicolas
>
> I'm not a huge fan of this approach.  With attributes, most use cases
> already had a natural line-break built in.  The only one that didn't was
> parameter attributes, and that was easy enough to work around by
> veritcalizing the parameter list, which is already common practice when it
> gets long.
>
> In this case, what you're proposing is I'd need to write something like
> this:
>
> class Foo
> #<Bar>
> implements Baz
> #<Beep>
> {
>     public do(
>     #Bar
>     $bar) : List
>     #<string>
>     )
> }
>


not so much - and only transitory for the libs that care about this - vs no
similar path in the proposed RFC as is:

class Foo#<T>
implements Baz#<U>
{
    public do(
        #<T> // <-  this could be a way to address your concern  Zebulan -
for Larry, that's already what we do for attributes on args
        DateTimeInterface
        $bar,
    ) : List#<string>
    {
        // [...]
    }
}


>
> That's just disgusting. :-)  I'm never going to do that.  I'll just write
> it properly, but now I have comment tags floating around my code forever
> that aren't actually comments.  Please, no.
>
> Really, Attributes' FC-friendliness was a one-off.  Pretty much any other
> new syntax we've added has always been a "upgrade or get a parse error,
> deal", like any other language.

I realize Symfony and its BC policy puts it in a position where a hard-cut
> to the new syntax would be harder than for most projects, but the cost is
> just way too high.
>

There's nothing specific about Symfony here - it's all just about making
adoption smooth if not just possible - broadly.
See perl6 or even python3 legacy on the topic.

Nicolas

Reply via email to