From: Nikita Popov Date: Fri, 6 Mar 2020 10:08:59 +0000 (+0100) Subject: Fixed bug #62609: Allow implementing Traversable in abstract class X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e9ae581f024e06878b2b1991b7daed6318c811a7;p=php Fixed bug #62609: Allow implementing Traversable in abstract class Master only, as this depends on fixes to calling order of interface implementation handlers. --- diff --git a/NEWS b/NEWS index 43de837425..5dca4c4770 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,8 @@ PHP NEWS checks). (Nikita) . Fixed bug #69084 (Unclear error message when not implementing a renamed abstract trait function). (Nikita) + . Fixed bug #62609 (Allow implementing Traversable on abstract classes). + (Nikita) - CURL: . Bumped required libcurl version to 7.29.0. (cmb) diff --git a/Zend/tests/bug62609.phpt b/Zend/tests/bug62609.phpt new file mode 100644 index 0000000000..9f4827d53a --- /dev/null +++ b/Zend/tests/bug62609.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #62609: Allow implementing Traversable on abstract classes (fail) +--FILE-- + +--EXPECT-- +Fatal error: Class NonAbstractTraversable must implement interface Traversable as part of either Iterator or IteratorAggregate in Unknown on line 0 diff --git a/Zend/tests/bug62609_2.phpt b/Zend/tests/bug62609_2.phpt new file mode 100644 index 0000000000..c59ac8c2de --- /dev/null +++ b/Zend/tests/bug62609_2.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #62609: Allow implementing Traversable on abstract classes (work) +--FILE-- + +--EXPECT-- +foo +bar diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index cf8b24d76a..acebe0a1fb 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -293,6 +293,11 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) { return SUCCESS; } + /* Abstract class can implement Traversable only, in which case the extending class must + * implement Iterator or IteratorAggregate. */ + if (class_type->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) { + return SUCCESS; + } if (class_type->num_interfaces) { ZEND_ASSERT(class_type->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); for (i = 0; i < class_type->num_interfaces; i++) {