@@ -507,6 +507,56 @@ static inheritance_status zend_perform_covariant_class_type_check(
507
507
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
508
508
}
509
509
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
+
510
560
static inheritance_status zend_perform_covariant_type_check (
511
561
zend_class_entry * fe_scope , zend_type fe_type ,
512
562
zend_class_entry * proto_scope , zend_type proto_type ) /* {{{ */
@@ -552,7 +602,9 @@ static inheritance_status zend_perform_covariant_type_check(
552
602
553
603
/* For intersection types loop over the parent types first as a child
554
604
* 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
+ ) {
556
608
/* First try to check whether we can succeed without resolving anything */
557
609
ZEND_TYPE_FOREACH (proto_type , single_type ) {
558
610
inheritance_status status ;
@@ -582,6 +634,39 @@ static inheritance_status zend_perform_covariant_type_check(
582
634
all_success = false;
583
635
}
584
636
} 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 ();
585
670
}
586
671
/* Only union or single types both in parent and child */
587
672
else {
0 commit comments