]> granicus.if.org Git - php/commitdiff
Allow overriding abstract methods
authorPedro Magalhães <mail@pmmaga.net>
Sat, 22 Apr 2017 16:41:54 +0000 (18:41 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 24 May 2017 15:42:01 +0000 (17:42 +0200)
RFC: https://wiki.php.net/rfc/allow-abstract-function-override

NEWS
UPGRADING
Zend/tests/abstract_inheritance_001.phpt [new file with mode: 0644]
Zend/tests/abstract_inheritance_002.phpt [new file with mode: 0644]
Zend/tests/abstract_inheritance_003.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

diff --git a/NEWS b/NEWS
index 8cce767459d86933fdecf0ce22449d4513a4ef8a..c231f50eda884f99e38c3554a4a039b4423c4965 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,8 @@ PHP                                                                        NEWS
     loosely-equal value). (pmmaga)
   . Fixed bug #61970 (Restraining __construct() access level in subclass gives
     a fatal error). (pmmaga)
+  . Fixed bug #63384 (Cannot override an abstract method with an abstract
+    method). (pmmaga, wes)
 
 - BCMath:
   . Fixed bug #46564 (bcmod truncates fractionals). (liborm85)
index 0530958def0260894f85fea47999778408c1f401..4a6169438376c7ec58bfe406869f4e15690b5128 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -101,6 +101,9 @@ PHP 7.2 UPGRADE NOTES
     inherited method. This complies with contravariance of method argument types
     under the Liskov Substitution Principle.
     (https://wiki.php.net/rfc/parameter-no-type-variance)
+  . It is now allowed to override an abstract method with another abstract
+    method in a child class.
+    (https://wiki.php.net/rfc/allow-abstract-function-override)
   . A trailing comma in group use statements is now allowed.
     (https://wiki.php.net/rfc/list-syntax-trailing-commas)
 
diff --git a/Zend/tests/abstract_inheritance_001.phpt b/Zend/tests/abstract_inheritance_001.phpt
new file mode 100644 (file)
index 0000000..9e061e6
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Allow abstract function override
+--FILE--
+<?php
+
+abstract class A           { abstract function bar($x); }
+abstract class B extends A { abstract function bar($x); }
+
+echo "DONE";
+?>
+--EXPECT--     
+DONE
diff --git a/Zend/tests/abstract_inheritance_002.phpt b/Zend/tests/abstract_inheritance_002.phpt
new file mode 100644 (file)
index 0000000..78f53c8
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Allow abstract function override
+--FILE--
+<?php
+
+abstract class A           { abstract function bar($x); }
+abstract class B extends A { abstract function bar($x, $y = 0); }
+
+echo "DONE";
+?>
+--EXPECT--     
+DONE
diff --git a/Zend/tests/abstract_inheritance_003.phpt b/Zend/tests/abstract_inheritance_003.phpt
new file mode 100644 (file)
index 0000000..24d5920
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Allow abstract function override
+--FILE--
+<?php
+
+abstract class A           { abstract function bar($x, $y = 0); }
+abstract class B extends A { abstract function bar($x); }
+
+echo "DONE";
+?>
+--EXPECTF--    
+Fatal error: Declaration of B::bar($x) must be compatible with A::bar($x, $y = 0) in %s
index 3a32215708fb8e8e2f0ac513cccb140ef0d4e8de..8f43d1560099d3874d3534d1b4e12febd3f9b1e8 100644 (file)
@@ -551,16 +551,6 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
        uint32_t child_flags;
        uint32_t parent_flags = parent->common.fn_flags;
 
-       if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
-               && parent->common.fn_flags & ZEND_ACC_ABSTRACT
-               && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
-               && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
-               zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
-                       ZSTR_VAL(parent->common.scope->name),
-                       ZSTR_VAL(child->common.function_name),
-                       child->common.prototype ? ZSTR_VAL(child->common.prototype->common.scope->name) : ZSTR_VAL(child->common.scope->name));
-       }
-
        if (UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
                zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name));
        }