On Thu, Aug 15, 2024, at 20:40, Rowan Tommins [IMSoP] wrote: > On 15/08/2024 16:22, Rob Landers wrote: >> Hello internals, >> >> I've decided to attempt an RFC for function autoloading. After reading >> hundreds of ancient (and recent) emails relating to the topic along with >> several abandoned RFCs from the past, and after much review, I've decided to >> put forth a variation of a previous RFC, as it seemed the least ambitious >> and the most likely to work: >> >> https://wiki.php.net/rfc/function_autoloading4 > > > Hi Rob, > > While brevity can sometimes be a virtue, I feel like there's a lot left to > the reader's interpretation here. > > Specifically, one of the main issues that has come up in previous discussions > of the topic is the behaviour of unqualified function names, which check the > current namespace first, then fall back to global scope. Your RFC implies an > approach to this, but doesn't actually spell it out, nor discuss its pros and > cons. >
It doesn't go too much into details here on purpose, especially since there was some recent discussion on changing the order. That being said, while writing the reply below, I realized it simply wasn't clear enough. I've updated the RFC to be more clear, in regards to the current behavior. > The fully qualified case is straight-forward: the autoloader is called, and > if still not defined, an error is thrown. But for the unqualified case, there > are multiple scenarios, and you only give the behaviour for one of them: > To fill in your chart: > Defined in current namespace? | Defined in global namespace? | Proposed > behaviour > ------------------------------+------------------------------+-------------------------------------- > No | No | Prefixed name > No | Yes | Prefixed name > Yes | No | No change > Yes | Yes | No change > > The third and fourth cases (where the function exists in the current > namespace) are straight-forward, although it wouldn't hurt to spell them out: > presumably, the namespaced function is used as now, so no autoloading is > needed. > > The complex case has always been the second one: the function doesn't exist > in the current namespace, but *does* exist in the global namespace. (Or, an > autoloader *defines* it in the global namespace.) > This should have the same behavior as in the class autoloader. In my attempt to be vague (in case the loading order is changed, which I assumed would affect class autoloading as well), I wasn't very clear on this. Meaning if you create a class called "Fiber" and a function called "strlen" in the current namespace, in unloaded files, an autoloader should be given the opportunity to load them. I should also probably define some vocabulary so this is all less confusing. and Done. > In concrete terms, what does this code output: > > spl_autoload_register( function($function, $type) { echo "$function..."; }, > type:SPL_AUTOLOAD_FUNCTION); > > namespace Foo { > foreach (['hello', 'goodbye'] as $word) { > echo strlen($word), ';'; > } > } > > a) "Foo\strlen...5;Foo\strlen...7;" (the autoloader is called every time the > function is encountered) > b) "Foo\strlen...5;7;" (the autoloader is called once, then somehow marked > not to run again for this name > c) "5;7;" (the autoloader is never run for this code) > I believe the "most correct" answer is (a) -- and is what the current class autoloader does as well. Option (b) would make it impossible to do any kind of dynamic code generation or old-fashioned file-based deployments. namespace global { spl_autoload_register(function ($function) { echo "$function..."; }); } namespace Foo { foreach (['hello', 'goodbye'] as $word) { if (!class_exists(Fiber::class)) { echo "Test..."; } } } Since I foresee (based on previous conversations) about people being worried about performance: I think this is best left to autoloader authors to manage. If there isn't a function autoloader, then there won't be any performance impact (or at least, minimal). However, if there is one, the author can take into account how their codebase works. For example, I highly suspect FIG will create a PSR for this (eventually), based on how they expect things to work. I suspect a project like WordPress could make use of it and implement things how they expect things to work, etc. For the case where you have a file full of unqualified `strlen()`'s, the autoloader author could create an option "do not shadow global functions" where it just returns immediately for built-in functions and doesn't even try autoloading (I also suspect there will be someone who code-golfs this to death so this check is extremely efficient). Is there a performance impact there? Probably not as big as you'd think -- and there already is a performance impact by using unqualified global functions (as shown in a recent proposal to change the order). So, if you are doing that already; you likely don't care about performance anyway. But I'm going to reserve any serious discussions about performance for when I have an actual implementation to play with (hopefully a PoC this weekend). > Note that there is an open RFC implementing option (b) by Gina and Dan here: > https://wiki.php.net/rfc/core-autoloading Last I heard, Gina was still hoping > to get back to it. > I went looking for this (I had sworn I had seen it last year), but unfortunately, I did not find it while searching the RFCs for prior work. I had thought it abandoned so I was looking in the wrong place. This RFC does not conflict with that RFC, if Gina/Dan were to pick it back up again. I may borrow the `function_exists()` change, which I just updated the RFC to do. > On a different note, there is no mention of autoloading namespaced constants > in this RFC, unlike in some previous proposals. Is this a conscious decision > to leave them out of scope, or an oversight? > I'm leaving them out on purpose to keep the scope tight. I've got a whole year ahead of me. > > > Regards, > > -- > Rowan Tommins > [IMSoP] — Rob