Skip to content

Commit e9ae581

Browse files
committed
Fixed bug #62609: Allow implementing Traversable in abstract class
Master only, as this depends on fixes to calling order of interface implementation handlers.
1 parent 125724c commit e9ae581

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ PHP NEWS
1414
checks). (Nikita)
1515
. Fixed bug #69084 (Unclear error message when not implementing a renamed
1616
abstract trait function). (Nikita)
17+
. Fixed bug #62609 (Allow implementing Traversable on abstract classes).
18+
(Nikita)
1719

1820
- CURL:
1921
. Bumped required libcurl version to 7.29.0. (cmb)

Zend/tests/bug62609.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Bug #62609: Allow implementing Traversable on abstract classes (fail)
3+
--FILE--
4+
<?php
5+
6+
abstract class AbstractTraversable implements Traversable {}
7+
8+
class NonAbstractTraversable extends AbstractTraversable {}
9+
10+
?>
11+
--EXPECT--
12+
Fatal error: Class NonAbstractTraversable must implement interface Traversable as part of either Iterator or IteratorAggregate in Unknown on line 0

Zend/tests/bug62609_2.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #62609: Allow implementing Traversable on abstract classes (work)
3+
--FILE--
4+
<?php
5+
6+
abstract class AbstractTraversable implements Traversable {}
7+
8+
class NonAbstractTraversable extends AbstractTraversable implements IteratorAggregate {
9+
public function getIterator() {
10+
yield "foo";
11+
yield "bar";
12+
}
13+
}
14+
15+
foreach (new NonAbstractTraversable as $value) {
16+
echo $value, "\n";
17+
}
18+
19+
?>
20+
--EXPECT--
21+
foo
22+
bar

Zend/zend_interfaces.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en
293293
if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
294294
return SUCCESS;
295295
}
296+
/* Abstract class can implement Traversable only, in which case the extending class must
297+
* implement Iterator or IteratorAggregate. */
298+
if (class_type->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
299+
return SUCCESS;
300+
}
296301
if (class_type->num_interfaces) {
297302
ZEND_ASSERT(class_type->ce_flags & ZEND_ACC_RESOLVED_INTERFACES);
298303
for (i = 0; i < class_type->num_interfaces; i++) {

0 commit comments

Comments
 (0)