On Fri, Jan 3, 2020 at 2:51 AM tyson andre <tysonandre...@hotmail.com>
wrote:

> After a quick search, it turns out I've mostly reinvented
> https://wiki.php.net/rfc/autofunc which I hadn't remembered.
> The `spl_autoload_*()` changes it mentions is what I had in mind
>
> There's been changes to php since then, it's been 7 years,
> and this adds thoughts on some implementation details.
>
> It's possible to support function / const autoloading
> in a way that keeps existing performance.
> Some of the objections at the time no longer apply.
>
> - `SOME_CONSTANT` no longer falls back to the literal string in php 8.
>   It throws an Error.
> - APC (used by some implementations) is no longer supported.
> - Many of the objections were against the available implementations
>   based on `function __autoload()`, not the concept of autoloading.
>
>   https://www.mail-archive.com/internals@lists.php.net/msg52307.html
> - There wasn't much traction from leads for the concept
>   or a Proof of Concept to vote on for that RFC (I think).
>
> What if an ambiguous `function_name()` or const outside the global
> namespace would attempt to autoload functions in the global namespace
> if it would throw an Error, but not the current namespace?
>
> `function_exists()` or `defined()` would not autoload,
> to preserve the behavior/performance of current programs.
> Anything with the callable type hint (e.g. `array_map`) would also need to
> be modified,
> but I think it already needs to do that for method arrays and
> 'MyClass::method'.
>
> - Same for global constants
> - That should avoid the performance hit - this autoloading would only be
> triggered
>   when php would previously throw an Error or warning
>   for undefined functions/constants.
> - This would also avoid the need to load polyfill files (e.g. mbstring)
>   or test framework files when their functions/constants are unused.
> - One blocker for other autoload proposals
>   seemed to be performance if I understood correctly
>   (e.g. attempting to autoload NS\strlen() every time strlen was called).
>
>   https://externals.io/message/54425#54616 and
> https://externals.io/message/54425#54655
>   detail this - choosing a different order of checks avoids the
> performance hit.
> - In addition to the RFC, changing the signatures to `defined(string
> $name, bool $autoload = false)`
>   and `function_exists($name, bool $autoload = false)`
>   might be useful ways to allow users to choose to autoload when checking
> for existence.
>
> And there'd have to be a hash map, flag, or other check
> to avoid recursion on the same constant/function.
>
> Background: A function call or constant usage is
> ambiguous if it could look for the function in two namespaces,
> as described by the rules documented in the below link.
> It's unambiguous if it ends up looking in only one namespace.
>
> https://www.php.net/manual/en/language.namespaces.rules.php
> The only type of ambiguous function call or global constant use is (7.):
>
> > 7. For unqualified names,
> >    if no import rule applies and the name refers to a function or
> constant
> >    and the code is outside the global namespace, the name is resolved at
> runtime.
> >    Assuming the code is in namespace A\B, here is how a call to function
> foo() is resolved:
> >    1. It looks for a function from the current namespace: A\B\foo().
> >    2. It tries to find and call the global function foo().
>
> My approach should be in line with the current name resolution
> for unqualified names outside the global namespace.
>
> 1. It (first) looks for a function from the current namespace: A\B\foo().
> 2. It (next) tries to find and call the global function foo().
> 3. (Optional) NEW ADDITION: Next, if both functions were undefined,
>    the autoloader(s) attempt to autoload the function A\B\foo()
>    (and call it instead of throwing if found) before proceeding to step
> (4.)
> 4. NEW ADDITION: If both functions were undefined,
>    the autoloader(s) attempt to autoload the global function foo()
>    (and call it instead of throwing if found) before throwing an Error
>
> And for unambiguous calls, find and autoload the only name it has.
>
> The fact that one of the two possible functions gets cached by the php VM
> in CACHED_PTR
> (for the lifetime of the request) the first time the function is found
> in either namespace will remain unchanged with this proposal.
>

I believe the problem here is this: The fact that the global function is
being cached, and continues to be cached when a namespaced function is
later defined, is a bug. See for example
https://bugs.php.net/bug.php?id=64346. We've never prioritized fixing this
issue, but implementing the proposed autoloading behavior would make fixing
it essentially impossible, as we certainly can't perform an autoloader
invocation on each call.

Nikita

Reply via email to