@@ -511,6 +511,56 @@ static inheritance_status zend_perform_covariant_class_type_check(
511
511
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
512
512
}
513
513
514
+ /* checks that the child type (being unique) is a subtype of each member of the parent intersection */
515
+ static inheritance_status zend_is_single_type_subtype_intersection (
516
+ zend_class_entry * fe_scope , zend_string * fe_class_name ,
517
+ zend_class_entry * fe_ce , zend_class_entry * proto_scope ,
518
+ zend_type proto_type , bool register_unresolved
519
+ ) {
520
+ bool have_unresolved = false;
521
+ zend_type * single_type ;
522
+ zend_type_list * parent_intersection_types ;
523
+
524
+ ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (proto_type ));
525
+
526
+ parent_intersection_types = ZEND_TYPE_LIST (proto_type );
527
+
528
+ ZEND_TYPE_LIST_FOREACH (parent_intersection_types , single_type ) {
529
+ zend_class_entry * proto_ce ;
530
+ zend_string * proto_class_name = NULL ;
531
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
532
+ proto_class_name =
533
+ resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
534
+ if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
535
+ continue ;
536
+ }
537
+
538
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
539
+ proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
540
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
541
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
542
+ proto_ce = ZEND_TYPE_CE (* single_type );
543
+ } else {
544
+ /* standard type cannot be part a subtype of an intersection type */
545
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
546
+ continue ;
547
+ }
548
+
549
+ if (!fe_ce || !proto_ce ) {
550
+ have_unresolved = true;
551
+ continue ;
552
+ }
553
+ if (!unlinked_instanceof (fe_ce , proto_ce )) {
554
+ return INHERITANCE_ERROR ;
555
+ }
556
+
557
+ track_class_dependency (fe_ce , fe_class_name );
558
+ track_class_dependency (proto_ce , proto_class_name );
559
+ } ZEND_TYPE_LIST_FOREACH_END ();
560
+
561
+ return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS ;
562
+ }
563
+
514
564
static inheritance_status zend_perform_covariant_type_check (
515
565
zend_class_entry * fe_scope , zend_type fe_type ,
516
566
zend_class_entry * proto_scope , zend_type proto_type , bool tentative ) /* {{{ */
@@ -563,7 +613,9 @@ static inheritance_status zend_perform_covariant_type_check(
563
613
564
614
/* For intersection types loop over the parent types first as a child
565
615
* can add them */
566
- if (ZEND_TYPE_IS_INTERSECTION (proto_type ) || ZEND_TYPE_IS_INTERSECTION (fe_type )) {
616
+ if (ZEND_TYPE_IS_INTERSECTION (fe_type )
617
+ || (ZEND_TYPE_IS_INTERSECTION (proto_type ) && !ZEND_TYPE_IS_UNION (fe_type ))
618
+ ) {
567
619
/* First try to check whether we can succeed without resolving anything */
568
620
ZEND_TYPE_FOREACH (proto_type , single_type ) {
569
621
inheritance_status status ;
@@ -593,6 +645,39 @@ static inheritance_status zend_perform_covariant_type_check(
593
645
all_success = false;
594
646
}
595
647
} ZEND_TYPE_FOREACH_END ();
648
+ } else if (ZEND_TYPE_IS_INTERSECTION (proto_type ) && ZEND_TYPE_IS_UNION (fe_type )) {
649
+ /* Here each member of the child union must be a subtype of the intersection */
650
+
651
+ /* First try to check whether we can succeed without resolving anything */
652
+ zend_type_list * child_union_types = ZEND_TYPE_LIST (fe_type );
653
+
654
+ ZEND_TYPE_LIST_FOREACH (child_union_types , single_type ) {
655
+ inheritance_status status ;
656
+ zend_string * fe_class_name ;
657
+ zend_class_entry * fe_ce = NULL ;
658
+
659
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
660
+ fe_class_name = resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
661
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
662
+ fe_ce = ZEND_TYPE_CE (* single_type );
663
+ fe_class_name = fe_ce -> name ;
664
+ } else {
665
+ /* standard type */
666
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
667
+ continue ;
668
+ }
669
+
670
+ status = zend_is_single_type_subtype_intersection (fe_scope ,
671
+ fe_class_name , fe_ce , proto_scope , proto_type ,
672
+ /* register_unresolved */ false);
673
+
674
+ if (status == INHERITANCE_ERROR ) {
675
+ return INHERITANCE_ERROR ;
676
+ }
677
+ if (status != INHERITANCE_SUCCESS ) {
678
+ all_success = false;
679
+ }
680
+ } ZEND_TYPE_LIST_FOREACH_END ();
596
681
}
597
682
/* Only union or single types both in parent and child */
598
683
else {
0 commit comments