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