@@ -616,6 +616,7 @@ static inheritance_status zend_perform_covariant_type_check(
616
616
* as the child can add types, however none of them can be a supertype of
617
617
* a parent type. */
618
618
if (ZEND_TYPE_IS_INTERSECTION (fe_type )) {
619
+ bool parent_union_has_unresolved = false;
619
620
/* First try to check whether we can succeed without resolving anything */
620
621
ZEND_TYPE_FOREACH (proto_type , single_type ) {
621
622
inheritance_status status ;
@@ -637,14 +638,33 @@ static inheritance_status zend_perform_covariant_type_check(
637
638
proto_scope , proto_class_name , proto_ce ,
638
639
fe_scope , fe_type , /* register_unresolved */ false);
639
640
640
- if (status == INHERITANCE_ERROR ) {
641
- return tentative ? INHERITANCE_WARNING : INHERITANCE_ERROR ;
642
- }
643
- if (status != INHERITANCE_SUCCESS ) {
644
- ZEND_ASSERT (status == INHERITANCE_UNRESOLVED );
645
- all_success = false;
641
+ /* If the parent is a union type then the intersection type must only be
642
+ * a subtype of one of them */
643
+ if (ZEND_TYPE_IS_UNION (proto_type )) {
644
+ if (status == INHERITANCE_SUCCESS ) {
645
+ return INHERITANCE_SUCCESS ;
646
+ }
647
+ if (status == INHERITANCE_UNRESOLVED ) {
648
+ all_success = false;
649
+ }
650
+ } else {
651
+ if (status == INHERITANCE_ERROR ) {
652
+ return tentative ? INHERITANCE_WARNING : INHERITANCE_ERROR ;
653
+ }
654
+ if (status != INHERITANCE_SUCCESS ) {
655
+ ZEND_ASSERT (status == INHERITANCE_UNRESOLVED );
656
+ parent_union_has_unresolved = true;
657
+ all_success = false;
658
+ }
646
659
}
647
660
} ZEND_TYPE_FOREACH_END ();
661
+
662
+ /* Reaching this means either the child intersection type is a valid/unresolved
663
+ * subtype of a parent single/intersection type, either it is an INvalid subtype
664
+ * when the parent is a union or it is unresolved, we check which case this is */
665
+ if (ZEND_TYPE_IS_UNION (proto_type ) && !parent_union_has_unresolved ) {
666
+ return tentative ? INHERITANCE_WARNING : INHERITANCE_ERROR ;
667
+ }
648
668
} else {
649
669
/* First try to check whether we can succeed without resolving anything */
650
670
ZEND_TYPE_FOREACH (fe_type , single_type ) {
0 commit comments