mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Deprecate direct access to static trait members
Static trait members may only be accessed through a class in which the trait is used, not directly on the trait. A complication here is that we should not store static methods/properties for which a deprecation is triggered in a cache slot. As the check for this is simple and cheap, I'm handling this in the cache slot population code in the VM. The alternative would be to pass the cache slot down into the fetching code. Part of https://wiki.php.net/rfc/deprecations_php_8_1.
This commit is contained in:
parent
cdbe39b16a
commit
a80360dbed
@ -330,6 +330,10 @@ PHP 8.1 UPGRADE NOTES
|
||||
e.g. a truncation from 1.9 to 1, is deprecated. This affects array keys,
|
||||
int parameter and return types, and operators working on integers.
|
||||
RFC: https://wiki.php.net/rfc/implicit-float-int-deprecate
|
||||
. Calling a static method or accessing a static property directly on a trait
|
||||
is deprecated. Static methods and properties should only be accessed on a
|
||||
class using the trait.
|
||||
RFC: https://wiki.php.net/rfc/deprecations_php_8_1
|
||||
. Returning a non-array from __sleep will raise a warning
|
||||
. Returning by reference from a void function is deprecated.
|
||||
RFC: https://wiki.php.net/rfc/deprecations_php_8_1
|
||||
|
64
Zend/tests/traits/direct_static_member_access.phpt
Normal file
64
Zend/tests/traits/direct_static_member_access.phpt
Normal file
@ -0,0 +1,64 @@
|
||||
--TEST--
|
||||
Direct access to static trait members is deprecated
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
trait T {
|
||||
public static $foo;
|
||||
public static function foo() {
|
||||
echo "Foo\n";
|
||||
}
|
||||
public static function __callStatic($name, $args) {
|
||||
echo "CallStatic($name)\n";
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
use T;
|
||||
}
|
||||
|
||||
function test() {
|
||||
T::$foo = 42;
|
||||
var_dump(T::$foo);
|
||||
T::foo();
|
||||
T::bar();
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
// Call twice to test cache slot behavior.
|
||||
test();
|
||||
test();
|
||||
|
||||
C::$foo = 42;
|
||||
var_dump(C::$foo);
|
||||
C::foo();
|
||||
C::bar();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Accessing static trait property T::$foo is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
|
||||
Deprecated: Accessing static trait property T::$foo is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
int(42)
|
||||
|
||||
Deprecated: Calling static trait method T::foo is deprecated, it should only be called on a class using the trait in %s on line %d
|
||||
Foo
|
||||
|
||||
Deprecated: Calling static trait method T::bar is deprecated, it should only be called on a class using the trait in %s on line %d
|
||||
CallStatic(bar)
|
||||
|
||||
|
||||
Deprecated: Accessing static trait property T::$foo is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
|
||||
Deprecated: Accessing static trait property T::$foo is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
int(42)
|
||||
|
||||
Deprecated: Calling static trait method T::foo is deprecated, it should only be called on a class using the trait in %s on line %d
|
||||
Foo
|
||||
|
||||
Deprecated: Calling static trait method T::bar is deprecated, it should only be called on a class using the trait in %s on line %d
|
||||
CallStatic(bar)
|
||||
|
||||
int(42)
|
||||
Foo
|
||||
CallStatic(bar)
|
@ -40,10 +40,19 @@ Bar::$parentProp = new Foo;
|
||||
var_dump(Bar::$selfProp, Bar::$selfNullProp, Bar::$parentProp);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Deprecated: Accessing static trait property Test::$selfProp is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
Cannot assign stdClass to property Test::$selfProp of type self
|
||||
|
||||
Deprecated: Accessing static trait property Test::$selfNullProp is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
Cannot assign stdClass to property Test::$selfNullProp of type ?self
|
||||
|
||||
Deprecated: Accessing static trait property Test::$parentProp is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
Cannot assign stdClass to property Test::$parentProp of type parent
|
||||
|
||||
Deprecated: Accessing static trait property Test::$selfNullProp is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
|
||||
Deprecated: Accessing static trait property Test::$selfNullProp is deprecated, it should only be accessed on a class using the trait in %s on line %d
|
||||
NULL
|
||||
object(Bar)#3 (0) {
|
||||
}
|
||||
|
@ -3024,7 +3024,8 @@ static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval
|
||||
|
||||
*prop_info = property_info;
|
||||
|
||||
if (EXPECTED(op1_type == IS_CONST)) {
|
||||
if (EXPECTED(op1_type == IS_CONST)
|
||||
&& EXPECTED(!(property_info->ce->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(cache_slot, ce, *retval);
|
||||
CACHE_PTR(cache_slot + sizeof(void *) * 2, property_info);
|
||||
}
|
||||
|
@ -1307,32 +1307,37 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
|
||||
lc_function_name = zend_string_tolower(function_name);
|
||||
}
|
||||
|
||||
zend_function *fbc;
|
||||
zval *func = zend_hash_find(&ce->function_table, lc_function_name);
|
||||
if (UNEXPECTED(!func)) {
|
||||
if (UNEXPECTED(!key)) {
|
||||
zend_string_release_ex(lc_function_name, 0);
|
||||
}
|
||||
return get_static_method_fallback(ce, function_name);
|
||||
}
|
||||
|
||||
zend_function *fbc = Z_FUNC_P(func);
|
||||
if (!(fbc->op_array.fn_flags & ZEND_ACC_PUBLIC)) {
|
||||
zend_class_entry *scope = zend_get_executed_scope();
|
||||
if (UNEXPECTED(fbc->common.scope != scope)) {
|
||||
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
|
||||
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
|
||||
zend_function *fallback_fbc = get_static_method_fallback(ce, function_name);
|
||||
if (!fallback_fbc) {
|
||||
zend_bad_method_call(fbc, function_name, scope);
|
||||
if (EXPECTED(func)) {
|
||||
fbc = Z_FUNC_P(func);
|
||||
if (!(fbc->op_array.fn_flags & ZEND_ACC_PUBLIC)) {
|
||||
zend_class_entry *scope = zend_get_executed_scope();
|
||||
if (UNEXPECTED(fbc->common.scope != scope)) {
|
||||
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
|
||||
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
|
||||
zend_function *fallback_fbc = get_static_method_fallback(ce, function_name);
|
||||
if (!fallback_fbc) {
|
||||
zend_bad_method_call(fbc, function_name, scope);
|
||||
}
|
||||
fbc = fallback_fbc;
|
||||
}
|
||||
fbc = fallback_fbc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fbc = get_static_method_fallback(ce, function_name);
|
||||
}
|
||||
|
||||
if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
zend_abstract_method_call(fbc);
|
||||
fbc = NULL;
|
||||
if (EXPECTED(fbc)) {
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
zend_abstract_method_call(fbc);
|
||||
fbc = NULL;
|
||||
} else if (UNEXPECTED(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT)) {
|
||||
zend_error(E_DEPRECATED,
|
||||
"Calling static trait method %s::%s is deprecated, "
|
||||
"it should only be called on a class using the trait",
|
||||
ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
||||
}
|
||||
}
|
||||
|
||||
if (UNEXPECTED(!key)) {
|
||||
@ -1428,6 +1433,13 @@ undeclared_property:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(ce->ce_flags & ZEND_ACC_TRAIT)) {
|
||||
zend_error(E_DEPRECATED,
|
||||
"Accessing static trait property %s::$%s is deprecated, "
|
||||
"it should only be accessed on a class using the trait",
|
||||
ZSTR_VAL(property_info->ce->name), ZSTR_VAL(property_name));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -3615,7 +3615,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (OP2_TYPE == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
|
@ -6812,7 +6812,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CONST == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -9139,7 +9140,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -9882,7 +9884,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_UNUSED == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -11489,7 +11492,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CV == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -23954,7 +23958,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CONST == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -26494,7 +26499,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -27788,7 +27794,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_UNUSED == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -30494,7 +30501,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CV == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -32626,7 +32634,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CONST == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -34523,7 +34532,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -34937,7 +34947,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_UNUSED == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
@ -37016,7 +37027,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (IS_CV == IS_CONST &&
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
|
||||
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
|
||||
EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
|
||||
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
|
||||
}
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
|
||||
|
Loading…
Reference in New Issue
Block a user