Skip to content

Commit ec484a0

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fix bug #80126
2 parents c80662a + 3b7c8bb commit ec484a0

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

Zend/tests/bug80126.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #80126: Covariant return types failing compilation
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function method(): I;
8+
}
9+
10+
abstract class A implements I {
11+
public function method(): I { }
12+
}
13+
14+
class C extends A { }
15+
16+
class C2 extends C {
17+
public function method(): C2 { }
18+
}
19+
20+
?>
21+
===DONE===
22+
--EXPECT--
23+
===DONE===

Zend/tests/bug80126_2.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #80126: Covariant return types failing compilation (variation 2)
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function method(): I;
8+
}
9+
10+
abstract class A implements I {
11+
public function method(): I {
12+
return new static();
13+
}
14+
}
15+
16+
class C extends A { }
17+
18+
interface I2 { }
19+
20+
class C2 extends C implements I2 {
21+
public function method(): C2 { }
22+
}
23+
24+
?>
25+
===DONE===
26+
--EXPECT--
27+
===DONE===

Zend/zend_inheritance.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,6 @@ static zend_class_entry *lookup_class(
272272

273273
/* Instanceof that's safe to use on unlinked classes. */
274274
static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
275-
zend_class_entry *ce;
276-
277275
if (ce1 == ce2) {
278276
return 1;
279277
}
@@ -282,18 +280,18 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce
282280
return instanceof_function(ce1, ce2);
283281
}
284282

285-
ce = ce1;
286-
while (ce->parent) {
287-
if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
288-
ce = ce->parent;
283+
if (ce1->parent) {
284+
zend_class_entry *parent_ce;
285+
if (ce1->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
286+
parent_ce = ce1->parent;
289287
} else {
290-
ce = zend_lookup_class_ex(ce->parent_name, NULL,
288+
parent_ce = zend_lookup_class_ex(ce1->parent_name, NULL,
291289
ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
292-
if (!ce) {
293-
break;
294-
}
295290
}
296-
if (ce == ce2) {
291+
292+
/* It's not sufficient to only check the parent chain itself, as need to do a full
293+
* recursive instanceof in case the parent interfaces haven't been copied yet. */
294+
if (parent_ce && unlinked_instanceof(parent_ce, ce2)) {
297295
return 1;
298296
}
299297
}
@@ -310,7 +308,7 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce
310308
}
311309
} else {
312310
for (i = 0; i < ce1->num_interfaces; i++) {
313-
ce = zend_lookup_class_ex(
311+
zend_class_entry *ce = zend_lookup_class_ex(
314312
ce1->interface_names[i].name, ce1->interface_names[i].lc_name,
315313
ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
316314
if (ce && unlinked_instanceof(ce, ce2)) {

0 commit comments

Comments
 (0)