@@ -606,24 +606,31 @@ static inheritance_status zend_perform_covariant_type_check(
606
606
bool have_unresolved = false;
607
607
608
608
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 ) {
611
619
ZEND_TYPE_FOREACH (fe_type , single_type ) {
612
620
zend_class_entry * fe_ce ;
613
621
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 );
617
624
if (!fe_ce ) {
618
625
fe_ce = lookup_class (fe_scope , fe_class_name );
619
626
}
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 ) {
626
628
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 ;
627
634
}
628
635
} ZEND_TYPE_FOREACH_END ();
629
636
}
0 commit comments