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
