mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Don't use separate static variables in inherited methods
RFC: https://wiki.php.net/rfc/static_variable_inheritance Closes GH-6719.
This commit is contained in:
parent
3e6b447979
commit
9a1da9f61f
24
UPGRADING
24
UPGRADING
@ -37,28 +37,26 @@ PHP 8.1 UPGRADE NOTES
|
||||
// is deprecated
|
||||
|
||||
RFC: https://wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg
|
||||
. When a method using static variables is inherited, the inherited method
|
||||
will now initialize the static variables to their original values, rather
|
||||
than the values at the time of inheritance:
|
||||
. When a method using static variables is inherited (but not overridden), the
|
||||
inherited method will now share static variables with the parent method.
|
||||
|
||||
class A {
|
||||
public function counter() {
|
||||
public static function counter() {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
return $counter;
|
||||
}
|
||||
}
|
||||
class B extends A {}
|
||||
|
||||
var_dump((new A)->counter()); // int(1)
|
||||
var_dump(A::counter()); // int(1)
|
||||
var_dump(A::counter()); // int(2)
|
||||
var_dump(B::counter()); // int(3), previously int(1)
|
||||
var_dump(B::counter()); // int(4), previously int(2)
|
||||
|
||||
eval('class B extends A {}'); // eval() to prevent early binding.
|
||||
|
||||
var_dump((new B)->counter()); // int(1), previously int(2)
|
||||
var_dump((new A)->counter()); // int(2)
|
||||
var_dump((new B)->counter()); // int(2), previously int(3)
|
||||
|
||||
Previously the behavior would be different depending on whether A::counter()
|
||||
was called before class B was declared, or after it was declared.
|
||||
This means that static variables in methods now behave the same way as
|
||||
static properties.
|
||||
RFC: https://wiki.php.net/rfc/static_variable_inheritance
|
||||
|
||||
- Fileinfo:
|
||||
. The fileinfo functions now accept and return, respectively, finfo objects
|
||||
|
@ -19,12 +19,15 @@ var_dump($d->foo(24));
|
||||
var_dump($c->foo());
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(42)
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(24)
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(42)
|
||||
int(24)
|
||||
}
|
||||
|
@ -19,13 +19,16 @@ var_dump($d->foo(24));
|
||||
var_dump($c->foo());
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
array(1) {
|
||||
[0]=>
|
||||
object(stdClass)#2 (0) {
|
||||
}
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(24)
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
object(stdClass)#2 (0) {
|
||||
}
|
||||
int(24)
|
||||
}
|
||||
|
@ -20,5 +20,5 @@ Bar::test();
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(2)
|
||||
int(1)
|
||||
int(2)
|
||||
int(3)
|
||||
int(4)
|
||||
|
43
Zend/tests/static_variables_traits.phpt
Normal file
43
Zend/tests/static_variables_traits.phpt
Normal file
@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
Behavior of static variables in trait methods
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
trait T {
|
||||
public static function counter() {
|
||||
static $i = 0;
|
||||
var_dump(++$i);
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {
|
||||
use T {
|
||||
T::counter as counter1;
|
||||
T::counter as counter2;
|
||||
}
|
||||
}
|
||||
|
||||
class C2 {
|
||||
use T;
|
||||
}
|
||||
|
||||
C1::counter();
|
||||
C1::counter1();
|
||||
C1::counter2();
|
||||
C2::counter();
|
||||
|
||||
C1::counter();
|
||||
C1::counter1();
|
||||
C1::counter2();
|
||||
C2::counter();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(1)
|
||||
int(1)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
@ -88,16 +88,7 @@ static zend_function *zend_duplicate_internal_function(zend_function *func, zend
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *zend_duplicate_user_function(zend_function *func) /* {{{ */
|
||||
{
|
||||
zend_op_array *new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
memcpy(new_op_array, func, sizeof(zend_op_array));
|
||||
zend_init_static_variables_map_ptr(new_op_array);
|
||||
return (zend_function *) new_op_array;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline zend_function *zend_duplicate_function(zend_function *func, zend_class_entry *ce, bool is_interface) /* {{{ */
|
||||
static zend_always_inline zend_function *zend_duplicate_function(zend_function *func, zend_class_entry *ce) /* {{{ */
|
||||
{
|
||||
if (UNEXPECTED(func->type == ZEND_INTERNAL_FUNCTION)) {
|
||||
return zend_duplicate_internal_function(func, ce);
|
||||
@ -108,12 +99,7 @@ static zend_always_inline zend_function *zend_duplicate_function(zend_function *
|
||||
if (EXPECTED(func->op_array.function_name)) {
|
||||
zend_string_addref(func->op_array.function_name);
|
||||
}
|
||||
if (is_interface
|
||||
|| EXPECTED(!func->op_array.static_variables)) {
|
||||
/* reuse the same op_array structure */
|
||||
return func;
|
||||
}
|
||||
return zend_duplicate_user_function(func);
|
||||
return func;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@ -948,9 +934,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
|
||||
|
||||
if (!check_only && child->common.prototype != proto && child_zv) {
|
||||
do {
|
||||
if (child->common.scope != ce
|
||||
&& child->type == ZEND_USER_FUNCTION
|
||||
&& !child->op_array.static_variables) {
|
||||
if (child->common.scope != ce && child->type == ZEND_USER_FUNCTION) {
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
/* Few parent interfaces contain the same method */
|
||||
break;
|
||||
@ -1021,7 +1005,7 @@ static zend_always_inline void do_inherit_method(zend_string *key, zend_function
|
||||
ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
|
||||
}
|
||||
|
||||
parent = zend_duplicate_function(parent, ce, is_interface);
|
||||
parent = zend_duplicate_function(parent, ce);
|
||||
|
||||
if (!is_interface) {
|
||||
_zend_hash_append_ptr(&ce->function_table, key, parent);
|
||||
|
@ -19,8 +19,8 @@ Bar::test();
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(2)
|
||||
int(1)
|
||||
int(2)
|
||||
int(3)
|
||||
int(4)
|
||||
|
||||
int(1)
|
||||
int(1)
|
||||
int(2)
|
||||
|
@ -763,7 +763,6 @@ static void zend_persist_class_method(zval *zv, zend_class_entry *ce)
|
||||
}
|
||||
|
||||
if ((op_array->fn_flags & ZEND_ACC_IMMUTABLE)
|
||||
&& !op_array->static_variables
|
||||
&& !ZCG(current_persistent_script)->corrupted
|
||||
&& zend_accel_in_shm(op_array)) {
|
||||
zend_shared_alloc_register_xlat_entry(op_array, op_array);
|
||||
|
Loading…
Reference in New Issue
Block a user