Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128392 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 8A3FE1A00BC for ; Tue, 5 Aug 2025 06:20:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1754374711; bh=G7h1XksCjgsnSWm/4N4cd1Vp5V++5hnt6KYQZ2yCtV8=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=HYjywaW3NjxHydtRylOIhmZptmnXkF3QLIBF1h+d5K9s+ZskfqKUg9xfO0kW6uZK/ mhhmpm9+i8xEYSy3/oSykL5Nt8Y+JNLh10qedBnQt7R2Y1qaXAN42/cqyUkonB8a8e nBVh/8GqIb2RG0T2KqW3CkNSTXx0wunlfoQI7dLKfzIjdcLCmSc9cMRlIiN9DaTWnc wiQmzkRxc9tau2UJoaO+KJRQ0cVmokR9RhU/Wu/klrUJu4oDSjGvO56jx9xzqcqaI9 ABJN9gG1ItxtKAC1ZS/enxv5Y1CewQw0yWitfzuvBnCc5RYO080OSAYcVK6L7/qFWA cRg30FJHdbL+Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0D66C180074 for ; Tue, 5 Aug 2025 06:18:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 5 Aug 2025 06:18:29 +0000 (UTC) Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 40FDA14001F5; Tue, 5 Aug 2025 02:20:09 -0400 (EDT) Received: from phl-imap-05 ([10.202.2.95]) by phl-compute-05.internal (MEProxy); Tue, 05 Aug 2025 02:20:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1754374809; x= 1754461209; bh=tY1sO6FASafcWpZXoPbOp4P/ZFOqVoOqlpK62hMUVGU=; b=D aMIupvCE1sqCjfdzHlyUcHom8c8Fn/GC4YArgRiMkKLCLclNduTAn3I8jD7KD9xF ejbc/ApGVxUJ7Kr8sPV1ICrjSEvenut4OJU/tlCcO48HHdDguGSJ1Aknsb9bVi8o 4X/FVMBuia+lgyUIta8zXRLf4EtgHAimcrtNDmHbbolg0bCjJw2X24KR9F7AY4wM jy75kB0GtFlzIGbGzbynQw/ieFrwDX67c7uLWIbg7/ffSIhCvZLK0ZMKbVOc7Bnq b8KG4c8Rc+HZAcH0qviwZsg8PqDD15A3TgQefKtJxP0rBM/dL8zQwnxeFT3PNc2q t7Y01fqGNcDFYtoSTFOWg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1754374809; x=1754461209; bh=tY1sO6FASafcWpZXoPbOp4P/ZFOqVoOqlpK 62hMUVGU=; b=ctDXG+q94ygYH0DG1yKiCMjUdgY2BYJj+koHYQmNZOQKw4q/yt4 Dpxp1+XqyzkZ6CiXZWMzE4S9BNzfpsswgThbyqxfR6nE9Zrf94MOYjmcyj0FrV0U tJdqAe+v6KAU/SoASyyQ3nlS9NMDa6mDeA+mNY7VrpgNdTHyeW9j4HrDAWsawb+8 kRQ6VubioLyrKGNAhkEENi7M38UuWJaKWkaEnq+RiGMrLjwaWc5VLJanpbPETzgp 15cqRXKRo00ccMjWvkcIynqbKhwkmGgeh4DG4y6vE1zGIVS8FowpDNDoqAK/Up+e hPR58wEL/TBgg8D+p82LO2ts6SaApd4vJrQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgdduudeggeegucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepofggfffhvfevkfgjfhfutgesrgdtreerredtjeenucfhrhhomhepfdftohgsucfn rghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurdgtohguvghsqeenucggtffrrghtth gvrhhnpeelkeefjeefteffvddvvdejgfduvdfggfeifedujeeijeetueeghfffveffhfdt jeenucffohhmrghinhepthhhvghphhhprdhfohhunhgurghtihhonhenucevlhhushhtvg hrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehrohgssegsohhtthhlvggu rdgtohguvghspdhnsggprhgtphhtthhopeefpdhmohguvgepshhmthhpohhuthdprhgtph htthhopehlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomhdprhgtphhtthhopehi nhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvghtpdhrtghpthhtoheplhgvvhhimh esphhhphdrnhgvth X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id C391A1820074; Tue, 5 Aug 2025 02:20:08 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: AEartZH3PTBN Date: Tue, 05 Aug 2025 08:19:47 +0200 To: "Levi Morrison" , "Larry Garfield" Cc: "php internals" Message-ID: <9e43bf45-af3c-428e-8cf2-16772382d25b@app.fastmail.com> In-Reply-To: References: Subject: Re: [PHP-DEV] Blog post: If we can get partial generics, should we? Content-Type: multipart/alternative; boundary=0b060c17862047519a0a757ff2a5ba2d From: rob@bottled.codes ("Rob Landers") --0b060c17862047519a0a757ff2a5ba2d Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Mon, Aug 4, 2025, at 22:49, Levi Morrison wrote: > On Mon, Aug 4, 2025 at 9:26=E2=80=AFAM Larry Garfield wrote: > > > > Hi folks. I recently wrote a blog post on behalf of the PHP Foundat= ion about some work Gina has been doing regarding generics. It's a foll= ow-up to last year's post on a similar topic. We are especially looking= for feedback from the Internals crew, and voters in particular, on whet= her or not to proceed. > > > > https://thephp.foundation/blog/2025/08/05/compile-generics/ > > > > Wearing my Internals/voter hat, my stance is a very strong "yes plea= se!" > > > > -- > > Larry Garfield > > larry@garfieldtech.com >=20 > I played with a few iterations of Gina's work. My opinion at that time > was that there are too many restrictions to be very useful. Based on > those evaluations, I would not consider it to be "80% of the > benefit.". With that said, maybe Gina has removed some of the > restrictions. Based on the article it , but I'll commit to trying it > out again. >=20 > One thing the article says we're missing and that we we definitely > need is unions, or at the very least the union with null. Nullable > types are everywhere, and even in your interfaces it's going to show > up. For instance, if we had interfaces for Set, Map, etc, there are > going to be operations which return nullable values. Sure, exceptions > can be thrown in some cases but not all of them. For instance, if you > are building a caching data structure, throwing an exceptions on a > cache miss would be very bad for performance*. You can separate it > into has + get, but this has two lookups which is not desirable for > performance. You can return a "tuple" like `[found, $value]` where > `$value` may be null, but this loses even more type safety, and isn't > a very common pattern in PHP. You really want `T|null`. >=20 > There are probably other "edges" that are important and should be > handled in this first pass, but missing nullable types is not a small > thing. >=20 > * We'll get a mini-optimization in PHP 8.5 for making the exception > object faster to construct, but it doesn't speed up the backtrace, > which is where most of the performance cost comes from in practice. If > you are benchmarking this, make sure to include cases where your stack > is a few dozen frames deep. I work for an observability company for my > day job, and it is insanely normal for there to be 10+ frames, and > still fairly common to be 30+ frames. Think about routing, frameworks, > middleware, helper functions, libraries and abstractions, etc. If you > use middleware in particular, expect 50+ frames to be normal. >=20 I have a few different ideas for unions/intersections, but to implement = them now would be refactoring for the sake of refactoring. There would b= e no benefit to implement any of it now. Earlier this year I tried interning types, so that type checking could b= e simple pointer equality. From there, I implemented a tri, such that in= tersections and unions were very fast to check.=20 The result is that it was virtually useless with today=E2=80=99s php, ex= cept for the most pathological cases. PHP doesn=E2=80=99t do much type c= hecking =E2=80=94 currently. In any case, the changes required to pull it off (not counting opcache) = were huge. If we were to run into the pathological cases more often (suc= h as with runtime generics), it might be worth it. All that being said, we are talking about *compile-time* generics. If th= ere is a time to be less efficient, it is during compilation, which gene= rally happens once (esp with opcache). Further, pathological type checki= ng is quite rare in codebases (most types are relatively simple without = deep hierarchical intersections and unions), so I assume it will be fine= to enable them. =E2=80=94 Rob --0b060c17862047519a0a757ff2a5ba2d Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

On Mon, Aug 4, 2025, at 22:49, Levi Morrison wrote:
On Mon, Aug 4, 2025 at 9:26=E2=80= =AFAM Larry Garfield <larry= @garfieldtech.com> wrote:
>
> Hi folks.=   I recently wrote a blog post on behalf of the PHP Foundation abou= t some work Gina has been doing regarding generics.  It's a follow-= up to last year's post on a similar topic.  We are especially looki= ng for feedback from the Internals crew, and voters in particular, on wh= ether or not to proceed.
>
>
=
> Wearing my Internals/voter hat, my stance is a very strong "ye= s please!"
>
> --
>   L= arry Garfield

I pl= ayed with a few iterations of Gina's work. My opinion at that time
=
was that there are too many restrictions to be very useful. Based o= n
those evaluations, I would not consider it to be "80% of the=
benefit.". With that said, maybe Gina has removed some of the=
restrictions. Based on the article it , but I'll commit to tr= ying it
out again.

One thing the arti= cle says we're missing and that we we definitely
need is union= s, or at the very least the union with null. Nullable
types ar= e everywhere, and even in your interfaces it's going to show
u= p. For instance, if we had interfaces for Set, Map, etc, there are
=
going to be operations which return nullable values. Sure, exceptio= ns
can be thrown in some cases but not all of them. For instan= ce, if you
are building a caching data structure, throwing an = exceptions on a
cache miss would be very bad for performance*.= You can separate it
into has + get, but this has two lookups = which is not desirable for
performance. You can return a "tupl= e" like `[found, $value]` where
`$value` may be null, but this= loses even more type safety, and isn't
a very common pattern = in PHP. You really want `T|null`.

There are pro= bably other "edges" that are important and should be
handled i= n this first pass, but missing nullable types is not a small
t= hing.

* We'll get a mini-optimization in PHP 8.= 5 for making the exception
object faster to construct, but it = doesn't speed up the backtrace,
which is where most of the per= formance cost comes from in practice. If
you are benchmarking = this, make sure to include cases where your stack
is a few doz= en frames deep. I work for an observability company for my
day= job, and it is insanely normal for there to be 10+ frames, and
still fairly common to be 30+ frames. Think about routing, frameworks,=
middleware, helper functions, libraries and abstractions, etc= . If you
use middleware in particular, expect 50+ frames to be= normal.


I have a f= ew different ideas for unions/intersections, but to implement them now w= ould be refactoring for the sake of refactoring. There would be no benef= it to implement any of it now.

Earlier this yea= r I tried interning types, so that type checking could be simple pointer= equality. From there, I implemented a tri, such that intersections and = unions were very fast to check. 

The resul= t is that it was virtually useless with today=E2=80=99s php, except for = the most pathological cases. PHP doesn=E2=80=99t do much type checking =E2= =80=94 currently.

In any case, the changes requ= ired to pull it off (not counting opcache) were huge. If we were to run = into the pathological cases more often (such as with runtime generics), = it might be worth it.

All that being said, we a= re talking about compile-time generics. If there is a time t= o be less efficient, it is during compilation, which generally happens o= nce (esp with opcache). Further, pathological type checking is quite rar= e in codebases (most types are relatively simple without deep hierarchic= al intersections and unions), so I assume it will be fine to enable them= .

=E2=80=94 Rob
--0b060c17862047519a0a757ff2a5ba2d--