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