@@ -507,6 +507,56 @@ static inheritance_status zend_perform_covariant_class_type_check(
507507 return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
508508}
509509
510+ /* checks that the child type (being unique) is a subtype of each member of the parent intersection */
511+ static inheritance_status zend_is_single_type_subtype_intersection (
512+ zend_class_entry * fe_scope , zend_string * fe_class_name ,
513+ zend_class_entry * fe_ce , zend_class_entry * proto_scope ,
514+ zend_type proto_type , bool register_unresolved
515+ ) {
516+ bool have_unresolved = false;
517+ zend_type * single_type ;
518+ zend_type_list * parent_intersection_types ;
519+
520+ ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (proto_type ));
521+
522+ parent_intersection_types = ZEND_TYPE_LIST (proto_type );
523+
524+ ZEND_TYPE_LIST_FOREACH (parent_intersection_types , single_type ) {
525+ zend_class_entry * proto_ce ;
526+ zend_string * proto_class_name = NULL ;
527+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
528+ proto_class_name =
529+ resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
530+ if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
531+ continue ;
532+ }
533+
534+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
535+ proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
536+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
537+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
538+ proto_ce = ZEND_TYPE_CE (* single_type );
539+ } else {
540+ /* standard type cannot be part a subtype of an intersection type */
541+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
542+ continue ;
543+ }
544+
545+ if (!fe_ce || !proto_ce ) {
546+ have_unresolved = true;
547+ continue ;
548+ }
549+ if (!unlinked_instanceof (fe_ce , proto_ce )) {
550+ return INHERITANCE_ERROR ;
551+ }
552+
553+ track_class_dependency (fe_ce , fe_class_name );
554+ track_class_dependency (proto_ce , proto_class_name );
555+ } ZEND_TYPE_LIST_FOREACH_END ();
556+
557+ return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS ;
558+ }
559+
510560static inheritance_status zend_perform_covariant_type_check (
511561 zend_class_entry * fe_scope , zend_type fe_type ,
512562 zend_class_entry * proto_scope , zend_type proto_type ) /* {{{ */
@@ -552,7 +602,9 @@ static inheritance_status zend_perform_covariant_type_check(
552602
553603 /* For intersection types loop over the parent types first as a child
554604 * can add them */
555- if (ZEND_TYPE_IS_INTERSECTION (proto_type ) || ZEND_TYPE_IS_INTERSECTION (fe_type )) {
605+ if (ZEND_TYPE_IS_INTERSECTION (fe_type )
606+ || (ZEND_TYPE_IS_INTERSECTION (proto_type ) && !ZEND_TYPE_IS_UNION (fe_type ))
607+ ) {
556608 /* First try to check whether we can succeed without resolving anything */
557609 ZEND_TYPE_FOREACH (proto_type , single_type ) {
558610 inheritance_status status ;
@@ -582,6 +634,39 @@ static inheritance_status zend_perform_covariant_type_check(
582634 all_success = false;
583635 }
584636 } ZEND_TYPE_FOREACH_END ();
637+ } else if (ZEND_TYPE_IS_INTERSECTION (proto_type ) && ZEND_TYPE_IS_UNION (fe_type )) {
638+ /* Here each member of the child union must be a subtype of the intersection */
639+
640+ /* First try to check whether we can succeed without resolving anything */
641+ zend_type_list * child_union_types = ZEND_TYPE_LIST (fe_type );
642+
643+ ZEND_TYPE_LIST_FOREACH (child_union_types , single_type ) {
644+ inheritance_status status ;
645+ zend_string * fe_class_name ;
646+ zend_class_entry * fe_ce = NULL ;
647+
648+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
649+ fe_class_name = resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
650+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
651+ fe_ce = ZEND_TYPE_CE (* single_type );
652+ fe_class_name = fe_ce -> name ;
653+ } else {
654+ /* standard type */
655+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
656+ continue ;
657+ }
658+
659+ status = zend_is_single_type_subtype_intersection (fe_scope ,
660+ fe_class_name , fe_ce , proto_scope , proto_type ,
661+ /* register_unresolved */ false);
662+
663+ if (status == INHERITANCE_ERROR ) {
664+ return INHERITANCE_ERROR ;
665+ }
666+ if (status != INHERITANCE_SUCCESS ) {
667+ all_success = false;
668+ }
669+ } ZEND_TYPE_LIST_FOREACH_END ();
585670 }
586671 /* Only union or single types both in parent and child */
587672 else {
0 commit comments