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

Reply via email to