Re: [Concept] Flip relative function lookup order (global, then local)
| From: | Rob Landers | Date: | Sat, 24 Aug 2024 20:36:43 +0000 |
| Subject: | Re: [Concept] Flip relative function lookup order (global, then local) | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-125193@lists.php.net to get a copy of this message | ||
On Sat, Aug 24, 2024, at 20:16, Stephen Reay wrote:
>
>
> > On 25 Aug 2024, at 00:01, Ilija Tovilo <tovilo.ilija@gmail.com> wrote:
> >
> > Hi Stephen
> >
> > On Sat, Aug 24, 2024 at 1:54 PM Stephen Reay <php-lists@koalephant.com> wrote:
> >>
> >> Thanks for clarifying. Out of curiosity, how much optimisation do you imagine would be
> >> possible if the lookups were done the same was as classes (ie no fallback, names must be local,
> >> qualified or imported with
use)?
> >
> > I haven't measured this case specifically, but if unqualified calls to
> > local functions are indeed rare (which the last analysis seems to
> > indicate), then it should make barely any difference. Of course, if
> > your code makes lots of use of them, then the story might be
> > different. That said, the penalty of an ambiguous internal call is
> > much higher than that of a user, local call, given that internal calls
> > sometimes have special optimizations or can even be entirely executed
> > at compile time. For local calls, it will simply lead to a double
> > lookup on first execution.
> >
> >> I am aware this is a BC break. But if it's kosher to discuss introducing a never
> >> ending BC break I don't see why this isn't a valid discussion either. It would give
> >> *everyone* that elusive 2-4% performance boost, would resolve any ambiguity about which function a
> >> person intended to call (the claimed security issue) and would bring consistency with the way
> >> classes/etc are referenced.
> >
> >> From my analysis, there were 2 967 unqualified calls to local
> > functions in the top 1 000 repositories. (Disclaimer: There might be a
> > "use function" at the top for some of these, the analysis isn't that
> > sophisticated.)
> >
> > I also ran the script to check for unqualified calls to global
> > functions (or at least functions that weren't statically visible in
> > that scope in any of the repositories files), and there were ~139 000
> > of them. It seems like this is quite a different beast. To summarize:
> >
> > 1. Flipping lookup order: ~a few dozens of changes
> > 2. Global only: ~3 000 changes
> > 3. Local only: ~139 000 changes
> >
> > While much of this can be automated, huge diffs still require
> > reviewing time, and can lead to many merge conflicts which also take
> > time to resolve. I would definitely prefer to go with 1. or
> > potentially 2.
> >
> > Ilija
> >
>
>
> Hi Ilija,
>
> I understand that a change like (3) is a huge BC break, and as I said earlier, I wasn't
> actually suggesting that is the action to take, because I don't think there is sufficient
> reason to take *any* action. But given that some people in this thread seem convinced that *a*
> change to functionality is apparently required, I do think every potential change, and it's
> pros and cons, should be discussed.
>
>
> As I've said numerous times, and been either outright dismissed or ignored: there has been
> a consistent push from a non-trivial number of internals members that userland developers should
> make better use of regular functions, rather than using classes as fancy namespaces. There was a
> recent RFC vote that implicitly endorsed this opinion.
>
> Right now, the lookup rules make namespaced regular functions a consistent experience for
> developers, but the lack of autoload makes it unpopular, and the lack of visibility for such symbols
> can be problematic.
>
> With the change you're proposing, there will be *another* hurdle that makes the use of
> regular namespaced functions harder/less intuitive, or potentially (with option 1) unpredictable
> over PHP versions, due to the constant threat of BC breaks due to new builtin functions - right when
> we have not one but two RFCs for function autoloading (arguably the biggest barrier to their
> increased usage in userland).
>
>
>
> So the whole reason I asked about (3) is because it would
> - (a) bring consistency with class/interface/trait symbols;
> - (b) inherently bring the much desired 2% performance boost for function calls, because people
> would be forced to qualify the names;
> - (c) have zero risk of of future WTF BC break when a new global function interrupting local
> function lookups;
> - (d) have no need for a new "simpler" qualifying syntax (you can't get shorter
> than 1 character);
> - (e) presumably simplify function autoloading, because there's no longer any
> "fallback" step to worry about before triggering an autoloader;
> - (e) even solve the "security" concerns John raised, because the developer would be
> forced to qualify their usage if they wanted to use the builtin function - their intent is always
> explicit, never guessed.
>
>
>
> Yes, it is a huge BC break in terms of the amount of code that's affected. But it's
> almost certainly one of the simplest BC break to "fix" in the history of PHP BC breaks.
>
>
> How much code was affected when register globals was removed? Or when magic quotes was removed?
> Or when short codes were removed?
>
> Surely any change being proposed here would mean a deprecation notice in the next release after
> 8.4, and then whatever actual change is proposed, in the next major version after that. So possibly
> 8.5 and then 9.0, but potentially 9.0 and then 10.0.
>
>
> If either of (1) or (2) is chosen, and the "acceptability" of such a choice depends
> on something less verbose than "namespace\" to qualify a local function, projects
> literally can't future proof (or no-deprecation-notice-proof, if you prefer) their code against
> the eventual flip until that change is implemented - in a scenario where a deprecation (and new
> local qualifier) goes out in 2025 as part of 8.5, and a flip happens in 2026 as part of 9.0, that
> would cuts the time projects have to effectively adapt, in half, and it means any code that's
> updated for it, can't make use of the new "less verbose" local qualifier if they also
> need to support versions prior to it being available.
>
> If it happened to be 9.0 and 10.0 being the deprecation and "change" versions,
> obviously people have longer to make the required change - but that argument cuts both ways. If you
> have 5 years to change every strlen to
> \strlen it's hardly going to cause a huge and sudden swath of
> noise in revision history. I would imagine most projects would just adopt a new code style, and
> prefixing with \ would occur automatically whenever a file is
> otherwise modified by a developer.
>
>
> There's also an impact on internals development/RFC with either (1) or (2): *any* proposed
> new global function in the standard library now has a BC barrier to pass if it *might* conflict with
> one defined by anyone in userland, in any namespace. JS is a living embodiment of of this problem:
> see String#includes, Array#includes, and Array#flat - and that's with people doing the
> "wrong thing" (extending builtin JS prototypes is arguably the same as using the
> \php namespace)
>
>
>
> Multiple people have lamented the way function fallbacks were originally implemented. If
> you're going to insist on making a change, let's at least aim for a change that brings
> *MORE* consistency, and fixes a previous mistake, rather than adding a brand new inconsistency and
> who knows how many years of unexpected BC breaks for unsuspecting userland developers - who
> apparently *already* stuggle to understand the way symbol lookup happens - into the future, and
> adding yet *another* reason for people to not use namespaced functions.
>
>
>
> Cheers
>
>
> Stephen
It may be worth waiting for function autoloading, to be honest. One of the nice things about it is
that you get called when using non-qualified globals. This makes it very easy for an autoloader to
start forcing qualified globals and emitting warnings/exceptions. I have a feeling that, eventually,
if function autoloading gets more use and accepted into php, we will see people using more and more
qualified globals.
Ergo, I suspect option (3) will become the default, eventually. Unless (2) is chosen, of course.
— Rob