Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:125113
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 qa.php.net (Postfix) with ESMTPS id DFC5C1A00BD
	for <internals@lists.php.net>; Fri, 23 Aug 2024 09:27:23 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
	t=1724405354; bh=AzDLIhHgTQhZExl5gCwuStMIO1yIwrkLoOV+cGqVG/E=;
	h=Subject:From:To:Date:In-Reply-To:References:From;
	b=YaPxyCFQwHZ+X2vbfUYYks9jQmVX/R/X9Tc1kKFK4PI7Y6g2KNEhVE8oGXouu73gH
	 w4R6J4yWdDsS7sgtxUe7NueCRP3YHfwu9pLkN/8XG6iGiurhp0Jsu93PebeT973BhC
	 f96MhRaqISmpVEDkqHaC2Bokm0FpGBerUmt+a1pRvGfE5g8y9whmHWM1v8zvEKRmgp
	 lgwyIxsFlo0BJsURTegBgdzhQs2MZ9FOX8US6+DOzmbuWP1VL3JuIRdUDKz4k8Rz87
	 X5tze8qegtIFg5zoXuG6PLaoQSsQ5SqunT8X8d5p6KRSeGRxy+3bG/T7ZWdhirGThL
	 Cji9raRHYgSPg==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id E515E180034
	for <internals@lists.php.net>; Fri, 23 Aug 2024 09:29:13 +0000 (UTC)
X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net
X-Spam-Level: 
X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED,
	DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_PASS,
	SPF_PASS autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: No
X-Envelope-From: <lists@ageofdream.com>
Received: from ageofdream.com (ageofdream.com [45.33.21.21])
	(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 <internals@lists.php.net>; Fri, 23 Aug 2024 09:29:13 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ageofdream.com;
	s=ageofdream; t=1724405241;
	bh=AzDLIhHgTQhZExl5gCwuStMIO1yIwrkLoOV+cGqVG/E=;
	h=Subject:From:To:Date:In-Reply-To:References:From;
	b=ptNVrzYu0Nb3+kJ2lW8FGUp7ga2qgMy0KYm8UkpHX8VkTbkybhYEIDRWZa4OlJJKJ
	 2AJbCCT/dLJNTkCVPzeH2IvR7Krku3kfIvypTR6HE0oQTPZtl361ni/ftgWmmivKut
	 wtcJCR1xLMz3dbFkfXdS0PXayz0ZZdhrR7Mj+e+MDPSF/m8YGKLY7eODhCFGvM6nTE
	 Em5nVrA+4y4XF1C8uPTNzHNBUhdDzbSoPWVlNcedBTTuizweYH8qhFFbJbYjwvToGH
	 VyF9NzyBHJlkEky4UGZ+NgxNpTRmNPc1UHQLV5s/lf4BcVTEMwA2qKcnAZLQHDXPwr
	 9UQazRM9S5lMw==
Received: from [192.168.1.7] (unknown [72.255.193.122])
	by ageofdream.com (Postfix) with ESMTPSA id 537B025095
	for <internals@lists.php.net>; Fri, 23 Aug 2024 05:27:21 -0400 (EDT)
Message-ID: <8086e7cf5061129eb002317b30aad4bb25811a1a.camel@ageofdream.com>
Subject: Re: [PHP-DEV] [Concept] Flip relative function lookup order
 (global, then local)
To: internals@lists.php.net
Date: Fri, 23 Aug 2024 05:27:20 -0400
In-Reply-To: <21D6F160-5EAE-44FA-907B-E1DAAC1B8D75@rwec.co.uk>
References: 
	<CAPyj-LCoBY2bPHLmsyONYDbY9aRSraLz5QNskeTiWfpMD0pTSg@mail.gmail.com>
	 <c385b525-37f7-446b-aa96-72272ef9e407@app.fastmail.com>
	 <CAPyj-LA4kTJTrQZUkn9kNMvWdH6SsFGU5mBO6EcpuUcRpXesgw@mail.gmail.com>
	 <d4b18a48-93b0-49c8-821d-f9298e831188@rwec.co.uk>
	 <b1ec48c9af091ebc3556d38a80566d6a02d4a1e3.camel@ageofdream.com>
	 <21D6F160-5EAE-44FA-907B-E1DAAC1B8D75@rwec.co.uk>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
User-Agent: Evolution 3.46.4-2 
Precedence: bulk
list-help: <mailto:internals+help@lists.php.net
list-unsubscribe: <mailto:internals+unsubscribe@lists.php.net>
list-post: <mailto:internals@lists.php.net>
List-Id: internals.lists.php.net
x-ms-reactions: disallow
MIME-Version: 1.0
From: lists@ageofdream.com (Nick Lockheart)

On Fri, 2024-08-23 at 09:16 +0100, Rowan Tommins [IMSoP] wrote:
>=20
>=20
> On 23 August 2024 01:42:38 BST, Nick Lockheart <lists@ageofdream.com>
> wrote:
> >=20
> > >=20
> > > BUT, if people already complain about "\" being ugly, having to
> > > write
> > > "namespace\" is going to make them REALLY grumpy...
> > > So maybe at the same time (or, probably, in advance) we need to
> > > come
> > > up with a nicer syntax for explicitly referencing the current
> > > namespace.
> >=20
> > =C2=A0=C2=A0 namespace foo using global functions;
> >=20
> > - or -=20
> >=20
> > =C2=A0=C2=A0 namespace foo using local functions;
> >=20
> >=20
> > Tell PHP what you want at the per-file level.
>=20
>=20
> This doesn't seem mutually exclusive to me. If you have a file where
> you've opted for "using global functions", you might want a way to
> reference a function in the current namespace.=20

Correct, so if you use the example:

    namespace foo using global functions;

you can write:

    array_key_exists();

and it will be resolved as global without a namespace lookup and will
use the dedicated opcode.

But if you need to use a local function you can do:

    \foo\sort();


The proposed global/local declaration as part of the namespace
declaration just turns off namespace lookups and sets the default
resolution for **unqualified** names.

Fully qualified names are not affected.


> It also doesn't address my other point, that having global as the
> default mode (even if we provide an option for local) is much less
> disruptive to existing code.


They are compatible, but related decisions.

I think it would be easier for people to accept a new PHP version where
unqualified names were always global, if we also had an option to make
local/namespaced the default resolution for *unqualified* names, on a
per-file basis, for those who need that.


Thus, there are multiple decision points:

1. Should we do namespace lookups on unqualified function calls at all?

2. If yes to 1, should we lookup in global first or local first?

3. Regardless of 1 or 2, should we let developers explicitly specify a
behavior for unqualified calls in the namespace declaration?

4. If yes to 1, should the behavior of namespace lookups change for
user-defined functions vs PHP built-in function names?


These aren't mutually exclusive, but they all work together to create a
complete behavior.

There are several ways that the above options could be combined:



### OPTION ONE ###

Using a regular namespace declaration still does an NS lookup, in the
same order, just like it normally works now.

That means that code that uses:

    namespace foo;

will behave exactly the same as today, with no BC breaks.

Developers using the new PHP version could opt-in to explicit namespace
behavior with:

    namespace foo using global functions;

or

    namespace foo using local functions;

In both cases, *fully-qualified* names still work the same.

Only *unqualified* names are affected by this directive, and they use
local only or global only, depending on the declaration.



### OPTION TWO ###

Namespace lookup is removed from a future version of PHP.

Code that uses the current namespace declaration:=20

    namespace foo;

will assume that all unqualified function calls are global scope.

To use a function in the local namespace, it can be fully qualified
with:

    \foo\MyFunction();


But, developers could also write:

     namespace foo using local functions;

And all unqualified function names would be resolved to local at
compile time. Global functions could still be accessed with a `\` if
this directive was used:

    \array_key_exists();



### OPTION THREE ###

Namespace lookup is removed from a future version of PHP.

Code that uses the current namespace declaration:

    namespace foo;

...will assume that an *unqualified* function name is a global function
*IF* it is a PHP built-in function.

Otherwise, *unqualified* function names that are *not* PHP built-in
functions will be presumed to be local to the namespace.

With Option Three, developers can still fully-qualify their functions:

    \foo\array_key_exists();

...to override a built-in name with a user function in the current
namespace.

Likewise, a fully-qualified:

    \MyFunction();

called from inside a namespace will still call the global function.

Only unqualified names are affected.

As an additional optional feature of Option Three, developers can
change this behavior with:

    namespace foo using global functions;

or

    namespace foo using local functions;


Only *unqualified* names are affected by this directive, and they use
local only or global only, depending on the namespace declaration.

In both cases, *fully-qualified* names still work the same.



Of course, there are many other possibilities that can be mixed-and-
matched.