@@ -513,6 +513,56 @@ static inheritance_status zend_perform_covariant_class_type_check(
513
513
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
514
514
}
515
515
516
+ /* checks that the child type (being unique) is a subtype of each member of the parent intersection */
517
+ static inheritance_status zend_is_single_type_subtype_intersection (
518
+ zend_class_entry * fe_scope , zend_string * fe_class_name ,
519
+ zend_class_entry * fe_ce , zend_class_entry * proto_scope ,
520
+ zend_type proto_type , bool register_unresolved
521
+ ) {
522
+ bool have_unresolved = false;
523
+ zend_type * single_type ;
524
+ zend_type_list * parent_intersection_types ;
525
+
526
+ ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (proto_type ));
527
+
528
+ parent_intersection_types = ZEND_TYPE_LIST (proto_type );
529
+
530
+ ZEND_TYPE_LIST_FOREACH (parent_intersection_types , single_type ) {
531
+ zend_class_entry * proto_ce ;
532
+ zend_string * proto_class_name = NULL ;
533
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
534
+ proto_class_name =
535
+ resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
536
+ if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
537
+ continue ;
538
+ }
539
+
540
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
541
+ proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
542
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
543
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
544
+ proto_ce = ZEND_TYPE_CE (* single_type );
545
+ } else {
546
+ /* standard type cannot be part a subtype of an intersection type */
547
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
548
+ continue ;
549
+ }
550
+
551
+ if (!fe_ce || !proto_ce ) {
552
+ have_unresolved = true;
553
+ continue ;
554
+ }
555
+ if (!unlinked_instanceof (fe_ce , proto_ce )) {
556
+ return INHERITANCE_ERROR ;
557
+ }
558
+
559
+ track_class_dependency (fe_ce , fe_class_name );
560
+ track_class_dependency (proto_ce , proto_class_name );
561
+ } ZEND_TYPE_LIST_FOREACH_END ();
562
+
563
+ return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS ;
564
+ }
565
+
516
566
static void register_unresolved_classes (zend_class_entry * scope , zend_type type ) {
517
567
zend_type * single_type ;
518
568
ZEND_TYPE_FOREACH (type , single_type ) {
@@ -575,7 +625,9 @@ static inheritance_status zend_perform_covariant_type_check(
575
625
576
626
/* For intersection types loop over the parent types first as a child
577
627
* can add them */
578
- if (ZEND_TYPE_IS_INTERSECTION (proto_type ) || ZEND_TYPE_IS_INTERSECTION (fe_type )) {
628
+ if (ZEND_TYPE_IS_INTERSECTION (fe_type )
629
+ || (ZEND_TYPE_IS_INTERSECTION (proto_type ) && !ZEND_TYPE_IS_UNION (fe_type ))
630
+ ) {
579
631
/* First try to check whether we can succeed without resolving anything */
580
632
ZEND_TYPE_FOREACH (proto_type , single_type ) {
581
633
inheritance_status status ;
@@ -605,6 +657,39 @@ static inheritance_status zend_perform_covariant_type_check(
605
657
all_success = false;
606
658
}
607
659
} ZEND_TYPE_FOREACH_END ();
660
+ } else if (ZEND_TYPE_IS_INTERSECTION (proto_type ) && ZEND_TYPE_IS_UNION (fe_type )) {
661
+ /* Here each member of the child union must be a subtype of the intersection */
662
+
663
+ /* First try to check whether we can succeed without resolving anything */
664
+ zend_type_list * child_union_types = ZEND_TYPE_LIST (fe_type );
665
+
666
+ ZEND_TYPE_LIST_FOREACH (child_union_types , single_type ) {
667
+ inheritance_status status ;
668
+ zend_string * fe_class_name ;
669
+ zend_class_entry * fe_ce = NULL ;
670
+
671
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
672
+ fe_class_name = resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
673
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
674
+ fe_ce = ZEND_TYPE_CE (* single_type );
675
+ fe_class_name = fe_ce -> name ;
676
+ } else {
677
+ /* standard type */
678
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
679
+ continue ;
680
+ }
681
+
682
+ status = zend_is_single_type_subtype_intersection (fe_scope ,
683
+ fe_class_name , fe_ce , proto_scope , proto_type ,
684
+ /* register_unresolved */ false);
685
+
686
+ if (status == INHERITANCE_ERROR ) {
687
+ return INHERITANCE_ERROR ;
688
+ }
689
+ if (status != INHERITANCE_SUCCESS ) {
690
+ all_success = false;
691
+ }
692
+ } ZEND_TYPE_LIST_FOREACH_END ();
608
693
}
609
694
/* Only union or single types both in parent and child */
610
695
else {
0 commit comments