Skip to content

Commit ea33768

Browse files
committed
Don't load classes of an intersection if parent has object
Refactor a bit the handling of iterable as a by product.
1 parent 129f1ad commit ea33768

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

Zend/tests/type_declarations/intersection_types/variance/invalid4.phpt renamed to Zend/tests/type_declarations/intersection_types/variance/valid9.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ class Test2 extends Test {
1313

1414
?>
1515
===DONE===
16-
--EXPECTF--
17-
Fatal error: Could not check compatibility between Test2::method(): X&Y and Test::method(): object, because class X is not available in %s on line %d
16+
--EXPECT--
17+
===DONE===

Zend/zend_inheritance.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -606,24 +606,31 @@ static inheritance_status zend_perform_covariant_type_check(
606606
bool have_unresolved = false;
607607

608608
if (ZEND_TYPE_IS_INTERSECTION(fe_type)) {
609-
if (proto_type_mask & (MAY_BE_OBJECT|MAY_BE_ITERABLE)) {
610-
bool any_class = (proto_type_mask & MAY_BE_OBJECT) != 0;
609+
/* As an intersection type can only be composed of class types (checked at compile stage),
610+
* it is trivially covariant to the object type.
611+
* Handle this case separately to ensure it never requires class loading. */
612+
if (proto_type_mask & MAY_BE_OBJECT) {
613+
return INHERITANCE_SUCCESS;
614+
}
615+
616+
// TODO: Make "iterable" an alias of "array|Traversable" instead,
617+
// so this special cases will be handled automatically.
618+
if (proto_type_mask & MAY_BE_ITERABLE) {
611619
ZEND_TYPE_FOREACH(fe_type, single_type) {
612620
zend_class_entry *fe_ce;
613621
zend_string *fe_class_name = get_class_from_type(&fe_ce, fe_scope, *single_type);
614-
if (!fe_class_name) {
615-
continue;
616-
}
622+
623+
ZEND_ASSERT(fe_class_name);
617624
if (!fe_ce) {
618625
fe_ce = lookup_class(fe_scope, fe_class_name);
619626
}
620-
if (fe_ce) {
621-
if (any_class || unlinked_instanceof(fe_ce, zend_ce_traversable)) {
622-
track_class_dependency(fe_ce, fe_class_name);
623-
return INHERITANCE_SUCCESS;
624-
}
625-
} else {
627+
if (!fe_ce) {
626628
have_unresolved = true;
629+
continue;
630+
}
631+
if (unlinked_instanceof(fe_ce, zend_ce_traversable)) {
632+
track_class_dependency(fe_ce, fe_class_name);
633+
return INHERITANCE_SUCCESS;
627634
}
628635
} ZEND_TYPE_FOREACH_END();
629636
}

0 commit comments

Comments
 (0)