@@ -450,6 +450,7 @@ static inheritance_status zend_perform_intersection_covariant_class_type_check(
450
450
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
451
451
}
452
452
453
+ /* Check whether a single class proto type is a subtype of a potentially complex fe_type. */
453
454
static inheritance_status zend_perform_covariant_class_type_check (
454
455
zend_class_entry * fe_scope , zend_string * fe_class_name , zend_class_entry * fe_ce ,
455
456
zend_class_entry * proto_scope , zend_type proto_type ) {
@@ -481,15 +482,19 @@ static inheritance_status zend_perform_covariant_class_type_check(
481
482
zend_type * single_type ;
482
483
483
484
/* Traverse the list of parent types and check if the current child (FE)
484
- * class is the subtype of at least one of them */
485
+ * class is the subtype of at least one of them (union) or all of them (intersection). */
486
+ bool is_intersection = ZEND_TYPE_IS_INTERSECTION (proto_type );
485
487
ZEND_TYPE_FOREACH (proto_type , single_type ) {
486
488
zend_class_entry * proto_ce ;
487
489
zend_string * proto_class_name = NULL ;
488
490
if (ZEND_TYPE_HAS_NAME (* single_type )) {
489
491
proto_class_name =
490
492
resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
491
493
if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
492
- return INHERITANCE_SUCCESS ;
494
+ if (!is_intersection ) {
495
+ return INHERITANCE_SUCCESS ;
496
+ }
497
+ continue ;
493
498
}
494
499
495
500
if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name );
@@ -499,69 +504,31 @@ static inheritance_status zend_perform_covariant_class_type_check(
499
504
proto_ce = ZEND_TYPE_CE (* single_type );
500
505
} else {
501
506
/* standard type */
507
+ ZEND_ASSERT (!is_intersection );
502
508
continue ;
503
509
}
504
510
505
511
if (!fe_ce || !proto_ce ) {
506
512
have_unresolved = 1 ;
507
- } else if (unlinked_instanceof (fe_ce , proto_ce )) {
513
+ continue ;
514
+ }
515
+ if (unlinked_instanceof (fe_ce , proto_ce )) {
508
516
track_class_dependency (fe_ce , fe_class_name );
509
517
track_class_dependency (proto_ce , proto_class_name );
510
- return INHERITANCE_SUCCESS ;
511
- }
512
- } ZEND_TYPE_FOREACH_END ();
513
-
514
- return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR ;
515
- }
516
-
517
- /* checks that the child type (being unique) is a subtype of each member of the parent intersection */
518
- static inheritance_status zend_is_single_type_subtype_intersection (
519
- zend_class_entry * fe_scope , zend_string * fe_class_name ,
520
- zend_class_entry * fe_ce , zend_class_entry * proto_scope ,
521
- zend_type proto_type , bool register_unresolved
522
- ) {
523
- bool have_unresolved = false;
524
- zend_type * single_type ;
525
- zend_type_list * parent_intersection_types ;
526
-
527
- ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (proto_type ));
528
-
529
- parent_intersection_types = ZEND_TYPE_LIST (proto_type );
530
-
531
- ZEND_TYPE_LIST_FOREACH (parent_intersection_types , single_type ) {
532
- zend_class_entry * proto_ce ;
533
- zend_string * proto_class_name = NULL ;
534
- if (ZEND_TYPE_HAS_NAME (* single_type )) {
535
- proto_class_name =
536
- resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
537
- if (zend_string_equals_ci (fe_class_name , proto_class_name )) {
538
- continue ;
518
+ if (!is_intersection ) {
519
+ return INHERITANCE_SUCCESS ;
539
520
}
540
-
541
- if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
542
- proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
543
- } else if (ZEND_TYPE_HAS_CE (* single_type )) {
544
- if (!fe_ce ) fe_ce = lookup_class (fe_scope , fe_class_name , register_unresolved );
545
- proto_ce = ZEND_TYPE_CE (* single_type );
546
521
} else {
547
- /* standard type cannot be part a subtype of an intersection type */
548
- ZEND_UNREACHABLE ();
549
- continue ;
550
- }
551
-
552
- if (!fe_ce || !proto_ce ) {
553
- have_unresolved = true;
554
- continue ;
555
- }
556
- if (!unlinked_instanceof (fe_ce , proto_ce )) {
557
- return INHERITANCE_ERROR ;
522
+ if (is_intersection ) {
523
+ return INHERITANCE_ERROR ;
524
+ }
558
525
}
526
+ } ZEND_TYPE_FOREACH_END ();
559
527
560
- track_class_dependency (fe_ce , fe_class_name );
561
- track_class_dependency (proto_ce , proto_class_name );
562
- } ZEND_TYPE_LIST_FOREACH_END ();
563
-
564
- return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS ;
528
+ if (have_unresolved ) {
529
+ return INHERITANCE_UNRESOLVED ;
530
+ }
531
+ return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR ;
565
532
}
566
533
567
534
static void register_unresolved_classes (zend_class_entry * scope , zend_type type ) {
@@ -694,16 +661,9 @@ static inheritance_status zend_perform_covariant_type_check(
694
661
continue ;
695
662
}
696
663
697
- if (UNEXPECTED (ZEND_TYPE_IS_INTERSECTION (proto_type ))) {
698
- status = zend_is_single_type_subtype_intersection (fe_scope ,
699
- fe_class_name , fe_ce , proto_scope , proto_type ,
700
- /* register_unresolved */ false);
701
- } else {
702
- status = zend_perform_covariant_class_type_check (fe_scope ,
703
- fe_class_name , fe_ce , proto_scope , proto_type ,
704
- /* register_unresolved */ false);
705
- }
706
-
664
+ status = zend_perform_covariant_class_type_check (fe_scope ,
665
+ fe_class_name , fe_ce , proto_scope , proto_type ,
666
+ /* register_unresolved */ false);
707
667
if (status == INHERITANCE_ERROR ) {
708
668
return INHERITANCE_ERROR ;
709
669
}
0 commit comments