@@ -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