Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129527 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 283041A00BC for ; Wed, 3 Dec 2025 16:43:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1764780225; bh=LamfG4C1hU9WVP8h8E3ZjuwuQNxHZcWltpCNWAz79y4=; h=Date:From:To:In-Reply-To:References:Subject:From; b=Umb6J0n/mZxx2Ceb78p88DP8z+rdc7s8Z8OYcEmNLwAl8t+8o0TSAX5Fr/cq3xs8e 2LewNAsPuMvVk3tfF7cGbKhfePG4+Z9zepeAUrB3lCjT9Xyfv+0e8V0g8qyaClP4P0 sq7Bvr2hJtslu/3IngkLGJKVlVkhFtEu/7L9wEGYGQK5NOn84Bs2TQflw3NCC+DAi+ a4RPSNFz91meCOn/sP6pjf5ctCXJeMd0Ts0vuDLmscMYKlasCdht3VXStlEDgBpjLY AnNHM4u6ER23fhCvJ505sd5zNKyAm+62aJS99Fqce5GPNw5O07+jaVdd/7i8y5BOOf pb05TDYnm+5cQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 63CAD180079 for ; Wed, 3 Dec 2025 16:43:44 +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=-0.1 required=5.0 tests=BAYES_50,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-b1-smtp.messagingengine.com (fhigh-b1-smtp.messagingengine.com [202.12.124.152]) (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 ; Wed, 3 Dec 2025 16:43:44 +0000 (UTC) Received: from phl-compute-12.internal (phl-compute-12.internal [10.202.2.52]) by mailfhigh.stl.internal (Postfix) with ESMTP id 7114A7A0133 for ; Wed, 3 Dec 2025 11:43:38 -0500 (EST) Received: from phl-imap-05 ([10.202.2.95]) by phl-compute-12.internal (MEProxy); Wed, 03 Dec 2025 11:43:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=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=fm2; t=1764780218; x=1764866618; bh=nVkMKcqGRt /8XNUxYvV9qVAhTMTqZG8Biy0SZG+da4o=; b=b9WzTtQ3cDYi/hGKFEdfMvcE7e fbTCmGJaq/nUwy6QU+i31Gbt/xSTTbuaNgXrBQ42BK8KA+ggMMMZ+CRcoDzjKznI kglMcDE05kBRvYp4Lo9UEgfge4rsItuJ5VnJ4AMULtxdDsqRwAyO6Mh7TGJqorsF 9MX2NQH1HEfRmXTE5Z2vqmAYIpp9786qf7MNQEmpX5gXDr64qvjxlEZtJaZCUePF c5NIkSxQ6AOoHBo65Bl+Yb7th5znuaIYjuYW/F/NI5G9CDNjqMADLzaGoGTeJtHI OjU1t6QYMzmW9PNBQao7ZqbZEqykJ4cbjeSzpNdVtlbD2sxpwQPLqZ+lk1VQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=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=fm1; t= 1764780218; x=1764866618; bh=nVkMKcqGRt/8XNUxYvV9qVAhTMTqZG8Biy0 SZG+da4o=; b=bg+VM42kpN0bQ8QSftC3avAPSD5uwI+1dJV9Cr9b/VCUOyMkm8O 2vmog2hHmYL2BYM5HoGqRRAEZDtPzWhVYSCT3X3I0pW5UzNWyPgKZ8j/FAI9Vrze 9WMMJIg6OOjLnXdI5lDR6FSTjGLSIXBvvorGQttL9RDws7G8/sna/UjcbRWZOiZ3 MyutPFnHnaHA79BlBqD5DYhzoiYc61AJ5hGMrtJtRU6CSAAa+r5sSgkAAeU5XpXX 3WVPv7gpfFyGt0yb+C1ECWxIKKqYiT4jq5ty6gCUQGrgJ7EMlhXob1eeJQkxWqmz fmkwVejH6LmBc/Avj1F7rrie0XoZosCf+Jg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgdeffedvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceurghi lhhouhhtmecufedttdenucenucfjughrpefoggffhffvkfgjfhfutgesrgdtreerredtje enucfhrhhomhepfdftohgsucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurdgt ohguvghsqeenucggtffrrghtthgvrhhnpedtueejtdethfeulefhtdelieduteelffdtud elheffgedtieehhfelieejgfevgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgr mhepmhgrihhlfhhrohhmpehrohgssegsohhtthhlvggurdgtohguvghspdhnsggprhgtph htthhopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehinhhtvghrnhgrlhhs sehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id D9FC51820074; Wed, 3 Dec 2025 11:43:37 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: AJmU-qZxpztc Date: Wed, 03 Dec 2025 17:41:54 +0100 To: internals@lists.php.net Message-ID: <0a420330-787f-4d1a-adb0-ab5ba52dd62a@app.fastmail.com> In-Reply-To: References: <87e9d1bf-e407-45c1-9fad-d8759405ab8b@app.fastmail.com> Subject: Re: [PHP-DEV] [RFC] Type Aliases Content-Type: multipart/alternative; boundary=c4550b5304d5413dbf993b3b0081edd5 From: rob@bottled.codes ("Rob Landers") --c4550b5304d5413dbf993b3b0081edd5 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Wed, Dec 3, 2025, at 16:51, Larry Garfield wrote: > Thanks, Rob! This does seem like a good low-hanging fruit piece to at= tack. Most importantly, I don't see anything here that would preclude m= ore formal TypeDef structures in the future. >=20 > A few other notes: >=20 > - Should `mixed` be allowed as in an alias definition? Since `mixed` = matches anything, it would render the entire alias redundant as it's the= n equivalent to `mixed`. This is already a compiler error: "Type mixed can only be used as a stan= dalone type." That being said, I guess this could be used to rename "mix= ed" to something else, but I don't know why you'd want to do that. I'd b= e open to throwing it in with "never" and "void", but "mixed" is an actu= al type that can be returned, which is why it wasn't. > - What if any conflict resolution is there if you include two differen= t type files that declare the same alias? It works the same as use in other ways: "Cannot use type DateTimeImmutable as DT because the name is already in = use" > - Because it's all compile time, I assume two aliases with the same so= urce but different names become compatible? =20 > Eg: >=20 > use type string|Stringable as Stringy; > use type string|Stringable as Stringish; >=20 > Those are mutually compatible in practice, yes? That's correct. You'd need typedefs to be able to enforce a difference t= here. >=20 > - Are aliases case sensitive? You're using Capitalized names in the R= FC, but I don't know if that means anything... (Please state in the RFC= .) Good catch; will do. For the record, it's as type-sensitive as any other= type in PHP (as in not case-sensitive at all). > - The "include type" syntax implies that it would not be possible to p= re-load aliases via Composer autoload or opcache preloading. (Well, may= be the latter.) That feels like an unnecessary limitation, and is my ma= in issue with the current design. Some way to have project-wide or pack= age-wide definitions would be very helpful, without needing a manual inc= lude statement in every file. Currently, we don't have packages or even "real" namespaces, so as much = as I'd want this, there'd need to be some settling on what authority a n= amespace really has. The amount of pushback that I got on the namespace-= private RFC indicates to me that people don't want namespaces to have an= y authority, but they want "packages" but nobody knows what a package is= ... but clearly, namespaces aren't anything. I digress. Sadly, no, this isn't possible with the current design. That = doesn't mean it can't be possible in the future, though, with some autol= oading overhaul or changes (see: Gina's Core Autoloading RFC under Draft= s). But currently, it has to pull off some shenanigans to compile the fi= le in the file (instead of during runtime like require and include). Hen= ce why type-files may only contain types and no other code. Basically, we just have to have some way to tell the compiler "also incl= ude these type aliases when compiling this file" -- that could be "every= file from here on out gets the aliases" (ie, a `use global type float|i= nt as Number` -- or something like that), or "include this type file" in= to this source file. The former would work best with today's current autoloader, but it would= be "trapped" in that paradigm and would make it harder to eventually cr= eate a "type autoloader". I could be wrong, though, and I'm open to othe= r people's ideas and opinions. I don't like the current implementation v= ery much, and while the former is much simpler to implement, I'm reasona= bly confident the current implementation can be improved. > - Does it matter where the `include type` statement goes? Must it be = at the top under the `use` statements, or could it be anywhere? It's basically a "copy this file right here", so it doesn't need to nece= ssarily be at the top, but trying to include it in a function would crea= te a syntax issue. I should clarify this in the RFC. > - Not allowing `use` statements in type include files: This feels like= a very unfortunate limitation. Is there any way to obviate that? It's= all compile time, as you said... I had to go make sure I didn't have a typo in there. I assume you mean n= amespaces? Namespaces in type files have a very weird problem once they = get included. For instance, namespaces are also compile-time prefixes, a= nd using statements are per namespace, not per file. By eliminating the = namespace, it becomes unambiguous that it=E2=80=99s per-file. That preve= nts shenanigans like: // my-types.php namespace Hello { use int|float as Number; // at the end of the namespace, the "use" is = lost } namespace World { use Number as Foo; // Number isn't a thing, neither is Hello\Number } Even just declaring a namespace for resolving types would create interes= ting effects: // my-types.php namespace Foo; use int|float as Number;=20 // alias actually becomes Foo\Number and gets cleared at the end of the = file In all reality, I generally expect tooling to make this easier. Like rig= ht-click the alias in your IDE and select: "move to type file" or someth= ing like that and have it automatically appended to your project's type = file. Same with typing a type in a type file and having it automatically= include it, just like it will automatically "use" a type outside of the= current namespace for you. > Overall, I am tentatively in favor. >=20 > --Larry Garfield Thanks! =E2=80=94 Rob --c4550b5304d5413dbf993b3b0081edd5 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
On Wed, Dec = 3, 2025, at 16:51, Larry Garfield wrote:
Thanks, Rob!  This does seem like a g= ood low-hanging fruit piece to attack.  Most importantly, I don't s= ee anything here that would preclude more formal TypeDef structures in t= he future.

A few other notes:

- Should `mixed` be allowed as in an alias definition?  Sin= ce `mixed` matches anything, it would render the entire alias redundant = as it's then equivalent to `mixed`.

This is already a compiler error: "Type mixed can only be used as a st= andalone type." That being said, I guess this could be used to rename "m= ixed" to something else, but I don't know why you'd want to do that. I'd= be open to throwing it in with "never" and "void", but "mixed" is an ac= tual type that can be returned, which is why it wasn't.
- What if an= y conflict resolution is there if you include two different type files t= hat declare the same alias?

It wor= ks the same as use in other ways:
"Cannot use type DateTimeImm= utable as DT because the name is already in use"

- Because it's all = compile time, I assume two aliases with the same source but different na= mes become compatible?  
Eg:

use type string|Stringable as Stringy;
use type string|Strin= gable as Stringish;

Those are mutually compatib= le in practice, yes?

That's correc= t. You'd need typedefs to be able to enforce a difference there.


- Are aliases case sensitive?  You're using Capitalized nam= es in the RFC, but I don't know if that means anything...  (Please = state in the RFC.)

Good catch; wil= l do. For the record, it's as type-sensitive as any other type in PHP (a= s in not case-sensitive at all).

- The "include type" syntax implies tha= t it would not be possible to pre-load aliases via Composer autoload or = opcache preloading.  (Well, maybe the latter.)  That feels lik= e an unnecessary limitation, and is my main issue with the current desig= n.  Some way to have project-wide or package-wide definitions would= be very helpful, without needing a manual include statement in every fi= le.

Currently, we don't have packa= ges or even "real" namespaces, so as much as I'd want this, there'd need= to be some settling on what authority a namespace really has. The amoun= t of pushback that I got on the namespace-private RFC indicates to me th= at people don't want namespaces to have any authority, but they want "pa= ckages" but nobody knows what a package is ... but clearly, namespaces a= ren't anything.

I digress. Sadly, no, this isn'= t possible with the current design. That doesn't mean it can't be possib= le in the future, though, with some autoloading overhaul or changes (see= : Gina's Core Autoloading RFC under Drafts). But currently, it has to pu= ll off some shenanigans to compile the file in the file (instead of duri= ng runtime like require and include). Hence why type-files may only cont= ain types and no other code.

Basically, we just= have to have some way to tell the compiler "also include these type ali= ases when compiling this file" -- that could be "every file from here on= out gets the aliases" (ie, a use global type float|int as Number -- or something lik= e that), or "include this type file" into this source file.
The former would work best with today's current autoloader,= but it would be "trapped" in that paradigm and would make it harder to = eventually create a "type autoloader". I could be wrong, though, and I'm= open to other people's ideas and opinions. I don't like the current imp= lementation very much, and while the former is much simpler to implement= , I'm reasonably confident the current implementation can be improved.

-= Does it matter where the `include type` statement goes?  Must it b= e at the top under the `use` statements, or could it be anywhere?
<= /blockquote>

It's basically a "copy this file right h= ere", so it doesn't need to necessarily be at the top, but trying to inc= lude it in a function would create a syntax issue. I should clarify this= in the RFC.

- Not allowing `use` statements in type include files: This= feels like a very unfortunate limitation.  Is there any way to obv= iate that?  It's all compile time, as you said...

I had to go make sure I didn't have a typo in there= . I assume you mean namespaces? Namespaces in type files have a very wei= rd problem once they get included. For instance, namespaces are also com= pile-time prefixes, and using statements are per namespace, not per file= . By eliminating the namespace, it becomes unambiguous that it=E2=80=99s= per-file. That prevents shenanigans like:

// my-types.php=0Anamespace Hel=
lo {=0A  use int|float as Number; // at the end of the namespace, the "u=
se" is lost=0A}=0A=0Anamespace World {=0A  use Number as Foo; // Number =
isn't a thing, neither is Hello\Number=0A}

Even= just declaring a namespace for resolving types would create interesting= effects:

// my-types.php=0Anamespace Foo;=0A=0Ause int|float as Number;=20=
=0A// alias actually becomes Foo\Number and gets cleared at the end of t=
he file

In all reality, I generally expect = tooling to make this easier. Like right-click the alias in your IDE and = select: "move to type file" or something like that and have it automatic= ally appended to your project's type file. Same with typing a type in a = type file and having it automatically include it, just like it will auto= matically "use" a type outside of the current namespace for you.

Overall= , I am tentatively in favor.

--Larry Garfield

Thanks!

=E2=80=94 Rob
--c4550b5304d5413dbf993b3b0081edd5--