Skip to content

[RFC] Flip ns call scope lookup order #14529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Zend/tests/bug74164.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ set_error_handler(function ($type, $msg) {
throw new \Exception($msg);
});

call_user_func(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable');
$fn = 'call_user_func';
$fn(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable');
?>
--EXPECTF--
Fatal error: Uncaught Exception: {closure:%s:%d}(): Argument #1 ($ref) must be passed by reference, value given in %s:%d
Stack trace:
#0 [internal function]: {closure:%s:%d}(2, '%s', '%s', 9)
#0 [internal function]: {closure:%s:%d}(2, '%s', '%s', 10)
#1 %sbug74164.php(%d): call_user_func(%s)
#2 {main}
thrown in %sbug74164.php on line %d
3 changes: 2 additions & 1 deletion Zend/tests/call_user_func_strict_arginfo_check.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ declare(strict_types=1);
namespace Foo;

// strlen() will be called with strict_types=0, so this is legal.
var_dump(call_user_func('strlen', false));
$fn = 'call_user_func';
var_dump($fn('strlen', false));

?>
--EXPECT--
Expand Down
3 changes: 1 addition & 2 deletions Zend/tests/frameless_jmp_004.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@ declare_local_class_exists();
var_dump(CLASS_EXISTS('Foo'));
?>
--EXPECT--
string(16) "Foo\class_exists"
bool(true)
bool(false)
2 changes: 1 addition & 1 deletion Zend/tests/ns_013.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ function strlen($x) {
echo strlen("Hello"),"\n";
?>
--EXPECT--
test\ns1\strlen
5
32 changes: 24 additions & 8 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,17 +614,17 @@ static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */
/* Original name */
int ret = zend_add_literal_string(&name);

/* Lowercased name */
zend_string *lc_name = zend_string_tolower(name);
zend_add_literal_string(&lc_name);

/* Lowercased unqualified name */
if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
lc_name = zend_string_alloc(unqualified_name_len, 0);
zend_string *lc_name = zend_string_alloc(unqualified_name_len, 0);
zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
zend_add_literal_string(&lc_name);
}

/* Lowercased name */
zend_string *lc_name = zend_string_tolower(name);
zend_add_literal_string(&lc_name);

return ret;
}
/* }}} */
Expand Down Expand Up @@ -1016,9 +1016,11 @@ static zend_string *zend_prefix_with_ns(zend_string *name) {
}
}

static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename);

static zend_string *zend_resolve_non_class_name(
zend_string *name, uint32_t type, bool *is_fully_qualified,
bool case_sensitive, HashTable *current_import_sub
bool case_sensitive, bool function
) {
char *compound;
*is_fully_qualified = 0;
Expand All @@ -1039,6 +1041,7 @@ static zend_string *zend_resolve_non_class_name(
return zend_prefix_with_ns(name);
}

HashTable *current_import_sub = function ? FC(imports_function) : FC(imports_const);
if (current_import_sub) {
/* If an unqualified name is a function/const alias, replace it. */
zend_string *import_name;
Expand Down Expand Up @@ -1070,20 +1073,33 @@ static zend_string *zend_resolve_non_class_name(
}
}

if (!compound && function) {
zend_string *lcname = zend_string_tolower(name);
zval *fbc_zv = zend_hash_find(CG(function_table), lcname);
if (fbc_zv
&& CG(active_op_array)
&& !zend_compile_ignore_function(Z_PTR_P(fbc_zv), CG(active_op_array)->filename)) {
*is_fully_qualified = true;
zend_string_release(lcname);
return zend_string_copy(name);
}
zend_string_release(lcname);
}

return zend_prefix_with_ns(name);
}
/* }}} */

static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
{
return zend_resolve_non_class_name(
name, type, is_fully_qualified, 0, FC(imports_function));
name, type, is_fully_qualified, 0, /* function */ true);
}

static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
{
return zend_resolve_non_class_name(
name, type, is_fully_qualified, 1, FC(imports_const));
name, type, is_fully_qualified, 1, /* function */ false);
}

static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
Expand Down
4 changes: 2 additions & 2 deletions benchmark/benchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ function main() {
$data['Zend/bench.php JIT'] = runBench(true);
$data['Symfony Demo 2.2.3'] = runSymfonyDemo(false);
$data['Symfony Demo 2.2.3 JIT'] = runSymfonyDemo(true);
$data['Wordpress 6.2'] = runWordpress(false);
$data['Wordpress 6.2 JIT'] = runWordpress(true);
// $data['Wordpress 6.2'] = runWordpress(false);
// $data['Wordpress 6.2 JIT'] = runWordpress(true);
$result = json_encode($data, JSON_PRETTY_PRINT) . "\n";

fwrite(STDOUT, $result);
Expand Down
7 changes: 4 additions & 3 deletions ext/reflection/tests/ReflectionFiber_notrace_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ ReflectionFiber should not segfault when inspecting fibers where the previous st

namespace test;

$f = new \Fiber(fn() => call_user_func(["Fiber", "suspend"]));
$fn = 'call_user_func';
$f = new \Fiber(fn() => $fn(["Fiber", "suspend"]));
$f->start();

$reflection = new \ReflectionFiber($f);
Expand All @@ -17,7 +18,7 @@ var_dump($reflection->getTrace());
?>
--EXPECTF--
string(%d) "%sReflectionFiber_notrace_2.php"
int(5)
int(6)
array(3) {
[0]=>
array(4) {
Expand All @@ -36,7 +37,7 @@ array(3) {
["file"]=>
string(%d) "%sReflectionFiber_notrace_2.php"
["line"]=>
int(5)
int(6)
["function"]=>
string(14) "call_user_func"
["args"]=>
Expand Down
5 changes: 3 additions & 2 deletions ext/zend_test/tests/observer_call_user_func_03.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ namespace Test {
echo 'my_function called' . PHP_EOL;
}

call_user_func('Test\\MyClass::myMethod');
call_user_func('Test\\my_function');
$fn = 'call_user_func';
$fn('Test\\MyClass::myMethod');
$fn('Test\\my_function');
}
?>
--EXPECTF--
Expand Down
5 changes: 3 additions & 2 deletions ext/zend_test/tests/observer_call_user_func_04.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ namespace Test {
echo 'my_function ' . $msg . PHP_EOL;
}

call_user_func_array('Test\\MyClass::myMethod', ['called']);
call_user_func_array('Test\\my_function', ['called']);
$fn = 'call_user_func_array';
$fn('Test\\MyClass::myMethod', ['called']);
$fn('Test\\my_function', ['called']);
}
?>
--EXPECTF--
Expand Down
6 changes: 3 additions & 3 deletions sapi/phpdbg/tests/print_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ Foo\Bar::Foo:
; (lines=5, args=1, vars=1, tmps=%d)
; %s:5-7
L0005 0000 CV0($bar) = RECV 1
L0006 0001 INIT_NS_FCALL_BY_NAME 1 string("Foo\\var_dump")
L0006 0002 SEND_VAR_EX CV0($bar) 1
L0006 0003 DO_FCALL
L0006 0001 INIT_FCALL %d %d string("var_dump")
L0006 0002 SEND_VAR CV0($bar) 1
L0006 0003 DO_ICALL
L0007 0004 RETURN null

Foo\Bar::baz:
Expand Down
Loading