mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Ignore inheritance rules on private methods
Closes GH-5401
This commit is contained in:
parent
371e29ef3a
commit
272b887b7b
9 changed files with 123 additions and 6 deletions
|
@ -194,6 +194,9 @@ PHP 8.0 UPGRADE NOTES
|
|||
RFC: https://wiki.php.net/rfc/locale_independent_float_to_string
|
||||
. Removed support for deprecated curly braces for offset access
|
||||
RFC: https://wiki.php.net/rfc/deprecate_curly_braces_array_access
|
||||
. Applying the final modifier on a private method will now produce a warning
|
||||
unless that method is the constructor.
|
||||
RFC: https://wiki.php.net/rfc/inheritance_private_methods
|
||||
|
||||
- COM:
|
||||
. Removed the ability to import case-insensitive constants from type
|
||||
|
@ -584,6 +587,10 @@ PHP 8.0 UPGRADE NOTES
|
|||
RFC: https://wiki.php.net/rfc/constructor_promotion
|
||||
. Added support for `match` expression.
|
||||
RFC: https://wiki.php.net/rfc/match_expression_v2
|
||||
. Private methods declared on a parent class no longer enforce any
|
||||
inheritance rules on the methods of a child class. (with the exception of
|
||||
final private constructors)
|
||||
RFC: https://wiki.php.net/rfc/inheritance_private_methods
|
||||
|
||||
- Date:
|
||||
. Added DateTime::createFromInterface() and
|
||||
|
|
|
@ -24,7 +24,7 @@ class C extends B {
|
|||
(new C)->test();
|
||||
|
||||
class D {
|
||||
private final function method(&$x) {
|
||||
private function method(&$x) {
|
||||
++$x;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6486,6 +6486,10 @@ zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name,
|
|||
|
||||
zend_string *lcname;
|
||||
|
||||
if ((fn_flags & ZEND_ACC_PRIVATE) && (fn_flags & ZEND_ACC_FINAL) && !zend_is_constructor(name)) {
|
||||
zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
|
||||
}
|
||||
|
||||
if (in_interface) {
|
||||
if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
|
||||
|
|
|
@ -828,6 +828,14 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
|
|||
uint32_t parent_flags = parent->common.fn_flags;
|
||||
zend_function *proto;
|
||||
|
||||
if (UNEXPECTED((parent_flags & ZEND_ACC_PRIVATE) && !(parent_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_CTOR))) {
|
||||
if (!check_only) {
|
||||
child->common.fn_flags |= ZEND_ACC_CHANGED;
|
||||
}
|
||||
/* The parent method is private and not an abstract so we don't need to check any inheritance rules */
|
||||
return INHERITANCE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!checked && UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
|
||||
if (check_only) {
|
||||
return INHERITANCE_ERROR;
|
||||
|
@ -869,10 +877,6 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
|
|||
child->common.fn_flags |= ZEND_ACC_CHANGED;
|
||||
}
|
||||
|
||||
if ((parent_flags & ZEND_ACC_PRIVATE) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
|
||||
return INHERITANCE_SUCCESS;
|
||||
}
|
||||
|
||||
proto = parent->common.prototype ?
|
||||
parent->common.prototype : parent;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ abstract class base {
|
|||
public $a = 'base';
|
||||
|
||||
// disallow cloning once forever
|
||||
final private function __clone() {}
|
||||
final protected function __clone() {}
|
||||
}
|
||||
|
||||
class test extends base {
|
||||
|
|
21
tests/classes/final_private_ctor.phpt
Normal file
21
tests/classes/final_private_ctor.phpt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
Final private constructors cannot be overridden
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Base
|
||||
{
|
||||
private final function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
class Extended extends Base
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot override final method Base::__construct() in %s on line %d
|
51
tests/classes/inheritance_007.phpt
Normal file
51
tests/classes/inheritance_007.phpt
Normal file
|
@ -0,0 +1,51 @@
|
|||
--TEST--
|
||||
Ensure private methods with the same name are not checked for inheritance rules - final
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
function callYourPrivates() {
|
||||
$this->normalPrivate();
|
||||
$this->finalPrivate();
|
||||
}
|
||||
function notOverridden_callYourPrivates() {
|
||||
$this->normalPrivate();
|
||||
$this->finalPrivate();
|
||||
}
|
||||
private function normalPrivate() {
|
||||
echo __METHOD__ . PHP_EOL;
|
||||
}
|
||||
final private function finalPrivate() {
|
||||
echo __METHOD__ . PHP_EOL;
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
function callYourPrivates() {
|
||||
$this->normalPrivate();
|
||||
$this->finalPrivate();
|
||||
}
|
||||
private function normalPrivate() {
|
||||
echo __METHOD__ . PHP_EOL;
|
||||
}
|
||||
final private function finalPrivate() {
|
||||
echo __METHOD__ . PHP_EOL;
|
||||
}
|
||||
}
|
||||
$a = new A();
|
||||
$a->callYourPrivates();
|
||||
$a->notOverridden_callYourPrivates();
|
||||
$b = new B();
|
||||
$b->callYourPrivates();
|
||||
$b->notOverridden_callYourPrivates();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Private methods cannot be final as they are never overridden by other classes %s
|
||||
|
||||
Warning: Private methods cannot be final as they are never overridden by other classes %s
|
||||
A::normalPrivate
|
||||
A::finalPrivate
|
||||
A::normalPrivate
|
||||
A::finalPrivate
|
||||
B::normalPrivate
|
||||
B::finalPrivate
|
||||
A::normalPrivate
|
||||
A::finalPrivate
|
16
tests/classes/inheritance_008.phpt
Normal file
16
tests/classes/inheritance_008.phpt
Normal file
|
@ -0,0 +1,16 @@
|
|||
--TEST--
|
||||
Ensure private methods with the same name are not checked for inheritance rules - static
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
static private function foo() { }
|
||||
private function bar() {}
|
||||
}
|
||||
class B extends A {
|
||||
private function foo() {}
|
||||
static private function bar() {}
|
||||
}
|
||||
echo 'OK';
|
||||
?>
|
||||
--EXPECT--
|
||||
OK
|
14
tests/classes/inheritance_009.phpt
Normal file
14
tests/classes/inheritance_009.phpt
Normal file
|
@ -0,0 +1,14 @@
|
|||
--TEST--
|
||||
Ensure private methods with the same name are not checked for inheritance rules - abstract
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
private function test() {}
|
||||
}
|
||||
abstract class B extends A {
|
||||
abstract function test();
|
||||
}
|
||||
echo 'OK';
|
||||
?>
|
||||
--EXPECT--
|
||||
OK
|
Loading…
Add table
Add a link
Reference in a new issue