Re: function autoloading v4 RFC
| From: | Rob Landers | Date: | Mon, 19 Aug 2024 23:21:22 +0000 |
| Subject: | Re: function autoloading v4 RFC | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-125056@lists.php.net to get a copy of this message | ||
On Mon, Aug 19, 2024, at 23:17, Rowan Tommins [IMSoP] wrote:
> On 19/08/2024 17:23, Rob Landers wrote:
>
> > As far as performance for ambiguous functions go, I was thinking of
> > submitting an RFC, where ambiguous function calls are tagged during
> > compilation and always resolve lexically, sorta like how it works now:
> >
> > echo strlen($x); // resolves to global, always
> > require_once "my-strlen";
> > echo strlen($x); // resolves to my strlen, always
> >
> > This works by basically rewriting the function name once resolved and
> > may make the code more predictable. If I can pull it off, it can be
> > relegated to a technical change that doesn’t need an RFC. Still
> > working on it.
>
>
> I'm not entirely clear what you're suggesting, but I think it might be
> either what already happens, or the same as Gina is proposing.
Yeah, that would be a separate RFC, so I didn't go into the weeds, but my point, is that it
would result in no change. But here we go :D
> Consider this code [https://3v4l.org/184k3]:
>
> namespace Foo;
>
> foreach ( [1,2,3] as $i ) {
> echo strlen('hello'), ' ';
> shadow_strlen();
> echo strlen('hello'), '; ';
> }
>
> function shadow_strlen() {
> if ( ! function_exists('Foo\\strlen') ) {
> function strlen($s) {
> return 42;
> }
> }
> }
>
> In PHP 5.3, this outputs '5 42; 42 42; 42 42;' That's fairly
> straight-forward: each time the function is called, the engine checks if
> "Foo\strlen" is defined.
>
> Since PHP 5.4, it outputs '5 42; 5 42; 5 42;' The engine caches the
> result of the lookup against each compiled opcode, so the first strlen()
> is cached as a call to \strlen() and the second as a call to \Foo\strlen().
>
> As I understand it, Gina is proposing that it would instead output '5 5;
> 5 5; 5 5;' - the function would be "pinned" by making "\Foo\strlen" an
>
> alias to "\strlen" for the rest of the program, and the function_exists
> call would immediately return true.
>
> Neither, as far as I can see, can happen at compile time, because the
> compiler doesn't know if and when a definition of \Foo\strlen() will be
> encountered.
To be fair, this isn't even really completely figured out yet. I was mostly wanting to point
out that it maybe could be a totally separate issue.. But, the gist is that at compile time, we can
mark a function as "ambiguous," meaning we don't really know if the function exists
(because it isn't fully qualified). The main issue with Gina's implementation (if I am
understanding it properly, and I potentially am not, so take this with a grain of salt) is that this
(https://3v4l.org/0jCpW) could fail if it were pinned, where before, it would not.
In my idea, a function becomes pinned until it isn't, with strict rules that kick it out of
being pinned and I think those rules are complex enough to warrant being a completely different RFC
or PR.
>
>
> > In other words, maybe pinning could be solved more generally in a
> > future RFC, decrease your RFC’s scope and chance for sharp edge cases.
>
> If anything, I think it would need to be the other way around: change
> the name resolution logic, so that an autoloading proposal was more
> palatable, because it didn't require running the autoloader an unbounded
> number of times for the same name.
>
> Proposing both at once seems reasonable, as the autoloading gives an
> extra benefit to outweigh the breaking change to shadowing behaviour.
>
> Regards,
I assume you are worried about something like this passing test?
--TEST--
show called only once
--FILE--
<?php
namespace test;
spl_autoload_register(function($name) {
echo "name=$name\n";
}, true, false, SPL_AUTOLOAD_FUNCTION);
echo strlen('foo');
echo strlen('bar');
echo strlen('baz');
?>
--EXPECT--
name=test\strlen
333
In my RFC, I mention it is called exactly once. I could maybe add it as a test in the PR. I've
committed it as another test on the RFC implementation.
>
> --
> Rowan Tommins
> [IMSoP]
>
— Rob