]> granicus.if.org Git - php/commitdiff
Fixed bug #62609: Allow implementing Traversable in abstract class
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 6 Mar 2020 10:08:59 +0000 (11:08 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 6 Mar 2020 10:12:43 +0000 (11:12 +0100)
Master only, as this depends on fixes to calling order of
interface implementation handlers.

NEWS
Zend/tests/bug62609.phpt [new file with mode: 0644]
Zend/tests/bug62609_2.phpt [new file with mode: 0644]
Zend/zend_interfaces.c

diff --git a/NEWS b/NEWS
index 43de837425fd8624b602e3a1439b0f54f545cd8a..5dca4c47709848bbe678893a2146abf20a2b8ecf 100644 (file)
--- 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 (file)
index 0000000..9f4827d
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Bug #62609: Allow implementing Traversable on abstract classes (fail)
+--FILE--
+<?php
+
+abstract class AbstractTraversable implements Traversable {}
+
+class NonAbstractTraversable extends AbstractTraversable {}
+
+?>
+--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 (file)
index 0000000..c59ac8c
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #62609: Allow implementing Traversable on abstract classes (work)
+--FILE--
+<?php
+
+abstract class AbstractTraversable implements Traversable {}
+
+class NonAbstractTraversable extends AbstractTraversable implements IteratorAggregate {
+    public function getIterator() {
+        yield "foo";
+        yield "bar";
+    }
+}
+
+foreach (new NonAbstractTraversable as $value) {
+    echo $value, "\n";
+}
+
+?>
+--EXPECT--
+foo
+bar
index cf8b24d76ab8da9bb9814844cc7aab7edc7dac74..acebe0a1fb729a5f5c39f62994c0584505153d15 100644 (file)
@@ -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++) {