@@ -482,6 +482,56 @@ static inheritance_status zend_perform_covariant_class_type_check(
482
482
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
483
483
}
484
484
485
+ /* checks that the child type (being unique) is a subtype of each member of the parent intersection */
486
+ static inheritance_status zend_is_single_type_subtype_intersection (
487
+ zend_class_entry * fe_scope , zend_string * fe_class_name ,
488
+ zend_class_entry * fe_ce , zend_class_entry * proto_scope ,
489
+ zend_type proto_type , bool register_unresolved
490
+ ) {
491
+ bool have_unresolved = false;
492
+ zend_type * single_type ;
493
+ zend_type_list * parent_intersection_types ;
494
+
495
+ ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (proto_type ));
496
+
497
+ parent_intersection_types = ZEND_TYPE_LIST (proto_type );
498
+
499
+ ZEND_TYPE_LIST_FOREACH (parent_intersection_types , single_type ) {
500
+ zend_class_entry * proto_ce ;
501
+ zend_string * proto_class_name = NULL ;
502
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
503
+ proto_class_name =
504
+ resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
505
+ if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
506
+ continue ;
507
+ }
508
+
509
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
510
+ proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
511
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
512
+ if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
513
+ proto_ce = ZEND_TYPE_CE (* single_type );
514
+ } else {
515
+ /* standard type cannot be part a subtype of an intersection type */
516
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
517
+ continue ;
518
+ }
519
+
520
+ if (!fe_ce || !proto_ce ) {
521
+ have_unresolved = true;
522
+ continue ;
523
+ }
524
+ if (!unlinked_instanceof (fe_ce , proto_ce )) {
525
+ return INHERITANCE_ERROR ;
526
+ }
527
+
528
+ track_class_dependency (fe_ce , fe_class_name );
529
+ track_class_dependency (proto_ce , proto_class_name );
530
+ } ZEND_TYPE_LIST_FOREACH_END ();
531
+
532
+ return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS ;
533
+ }
534
+
485
535
static inheritance_status zend_perform_covariant_type_check (
486
536
zend_class_entry * fe_scope , zend_type fe_type ,
487
537
zend_class_entry * proto_scope , zend_type proto_type ) /* {{{ */
@@ -527,7 +577,9 @@ static inheritance_status zend_perform_covariant_type_check(
527
577
528
578
/* For intersection types loop over the parent types first as a child
529
579
* can add them */
530
- if (ZEND_TYPE_IS_INTERSECTION (proto_type ) || ZEND_TYPE_IS_INTERSECTION (fe_type )) {
580
+ if (ZEND_TYPE_IS_INTERSECTION (fe_type )
581
+ || (ZEND_TYPE_IS_INTERSECTION (proto_type ) && !ZEND_TYPE_IS_UNION (fe_type ))
582
+ ) {
531
583
/* First try to check whether we can succeed without resolving anything */
532
584
ZEND_TYPE_FOREACH (proto_type , single_type ) {
533
585
inheritance_status status ;
@@ -557,6 +609,39 @@ static inheritance_status zend_perform_covariant_type_check(
557
609
all_success = false;
558
610
}
559
611
} ZEND_TYPE_FOREACH_END ();
612
+ } else if (ZEND_TYPE_IS_INTERSECTION (proto_type ) && ZEND_TYPE_IS_UNION (fe_type )) {
613
+ /* Here each member of the child union must be a subtype of the intersection */
614
+
615
+ /* First try to check whether we can succeed without resolving anything */
616
+ zend_type_list * child_union_types = ZEND_TYPE_LIST (fe_type );
617
+
618
+ ZEND_TYPE_LIST_FOREACH (child_union_types , single_type ) {
619
+ inheritance_status status ;
620
+ zend_string * fe_class_name ;
621
+ zend_class_entry * fe_ce = NULL ;
622
+
623
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
624
+ fe_class_name = resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
625
+ } else if (ZEND_TYPE_HAS_CE (* single_type )) {
626
+ fe_ce = ZEND_TYPE_CE (* single_type );
627
+ fe_class_name = fe_ce -> name ;
628
+ } else {
629
+ /* standard type */
630
+ ZEND_ASSERT (0 && "This shouldn't happen yet" );
631
+ continue ;
632
+ }
633
+
634
+ status = zend_is_single_type_subtype_intersection (fe_scope ,
635
+ fe_class_name , fe_ce , proto_scope , proto_type ,
636
+ /* register_unresolved */ false);
637
+
638
+ if (status == INHERITANCE_ERROR ) {
639
+ return INHERITANCE_ERROR ;
640
+ }
641
+ if (status != INHERITANCE_SUCCESS ) {
642
+ all_success = false;
643
+ }
644
+ } ZEND_TYPE_LIST_FOREACH_END ();
560
645
}
561
646
/* Only union or single types both in parent and child */
562
647
else {
0 commit comments