@@ -406,8 +406,7 @@ static void track_class_dependency(zend_class_entry *ce, zend_string *class_name
406
406
/* Check whether any type in the fe_type intersection type is a subtype of the proto class. */
407
407
static inheritance_status zend_is_intersection_subtype_of_class (
408
408
zend_class_entry * fe_scope , zend_type fe_type ,
409
- zend_class_entry * proto_scope , zend_string * proto_class_name , zend_class_entry * proto_ce ,
410
- bool register_unresolved )
409
+ zend_class_entry * proto_scope , zend_string * proto_class_name , zend_class_entry * proto_ce )
411
410
{
412
411
ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (fe_type ));
413
412
bool have_unresolved = false;
@@ -425,11 +424,10 @@ static inheritance_status zend_is_intersection_subtype_of_class(
425
424
return INHERITANCE_SUCCESS ;
426
425
}
427
426
428
- if (!proto_ce ) proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
429
- fe_ce =
430
- lookup_class (fe_scope , fe_class_name , register_unresolved );
427
+ if (!proto_ce ) proto_ce = lookup_class (proto_scope , proto_class_name );
428
+ fe_ce = lookup_class (fe_scope , fe_class_name );
431
429
} else if (ZEND_TYPE_HAS_CE (* single_type )) {
432
- if (!proto_ce ) proto_ce = lookup_class (proto_scope , proto_class_name , register_unresolved );
430
+ if (!proto_ce ) proto_ce = lookup_class (proto_scope , proto_class_name );
433
431
fe_ce = ZEND_TYPE_CE (* single_type );
434
432
} else {
435
433
/* standard type in an intersection type is impossible,
@@ -533,6 +531,19 @@ static inheritance_status zend_is_class_subtype_of_type(
533
531
return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR ;
534
532
}
535
533
534
+ static zend_string * get_class_from_type (
535
+ zend_class_entry * * ce , zend_class_entry * scope , zend_type single_type ) {
536
+ if (ZEND_TYPE_HAS_NAME (single_type )) {
537
+ * ce = NULL ;
538
+ return resolve_class_name (scope , ZEND_TYPE_NAME (single_type ));
539
+ }
540
+ if (ZEND_TYPE_HAS_CE (single_type )) {
541
+ * ce = ZEND_TYPE_CE (single_type );
542
+ return (* ce )-> name ;
543
+ }
544
+ return NULL ;
545
+ }
546
+
536
547
static void register_unresolved_classes (zend_class_entry * scope , zend_type type ) {
537
548
zend_type * single_type ;
538
549
ZEND_TYPE_FOREACH (type , single_type ) {
@@ -595,15 +606,26 @@ static inheritance_status zend_perform_covariant_type_check(
595
606
bool have_unresolved = false;
596
607
597
608
if (ZEND_TYPE_IS_INTERSECTION (fe_type )) {
598
- if (proto_type_mask & MAY_BE_OBJECT ) {
599
- /* TODO We can't just return success here, because the class must be loaded. */
600
- }
601
- if (proto_type_mask & MAY_BE_ITERABLE ) {
602
- /* TODO */
603
- }
604
- if (proto_type_mask ) {
605
- /* An intersection type cannot be a subtype of other builtin types. */
606
- return INHERITANCE_ERROR ;
609
+ if (proto_type_mask & (MAY_BE_OBJECT |MAY_BE_ITERABLE )) {
610
+ bool any_class = (proto_type_mask & MAY_BE_OBJECT ) != 0 ;
611
+ ZEND_TYPE_FOREACH (fe_type , single_type ) {
612
+ zend_class_entry * fe_ce ;
613
+ zend_string * fe_class_name = get_class_from_type (& fe_ce , fe_scope , * single_type );
614
+ if (!fe_class_name ) {
615
+ continue ;
616
+ }
617
+ if (!fe_ce ) {
618
+ fe_ce = lookup_class (fe_scope , fe_class_name );
619
+ }
620
+ if (fe_ce ) {
621
+ if (any_class || unlinked_instanceof (fe_ce , zend_ce_traversable )) {
622
+ track_class_dependency (fe_ce , fe_class_name );
623
+ return INHERITANCE_SUCCESS ;
624
+ }
625
+ } else {
626
+ have_unresolved = true;
627
+ }
628
+ } ZEND_TYPE_FOREACH_END ();
607
629
}
608
630
609
631
/* U_1&...&U_n < V_1&...&V_m if forall V_j. exists U_i. U_i < V_j.
@@ -613,22 +635,15 @@ static inheritance_status zend_perform_covariant_type_check(
613
635
early_exit_status =
614
636
ZEND_TYPE_IS_INTERSECTION (proto_type ) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS ;
615
637
ZEND_TYPE_FOREACH (proto_type , single_type ) {
616
- inheritance_status status ;
617
- zend_string * proto_class_name ;
618
- zend_class_entry * proto_ce = NULL ;
619
-
620
- if (ZEND_TYPE_HAS_NAME (* single_type )) {
621
- proto_class_name = resolve_class_name (proto_scope , ZEND_TYPE_NAME (* single_type ));
622
- } else if (ZEND_TYPE_HAS_CE (* single_type )) {
623
- proto_ce = ZEND_TYPE_CE (* single_type );
624
- proto_class_name = proto_ce -> name ;
625
- } else {
638
+ zend_class_entry * proto_ce ;
639
+ zend_string * proto_class_name =
640
+ get_class_from_type (& proto_ce , proto_scope , * single_type );
641
+ if (!proto_class_name ) {
626
642
continue ;
627
643
}
628
644
629
- status = zend_is_intersection_subtype_of_class (
630
- fe_scope , fe_type , proto_scope , proto_class_name , proto_ce ,
631
- /* register_unresolved */ false);
645
+ inheritance_status status = zend_is_intersection_subtype_of_class (
646
+ fe_scope , fe_type , proto_scope , proto_class_name , proto_ce );
632
647
if (status == early_exit_status ) {
633
648
return status ;
634
649
}
@@ -643,22 +658,14 @@ static inheritance_status zend_perform_covariant_type_check(
643
658
* whether proto_type is a union or intersection (only the inner check differs). */
644
659
early_exit_status = INHERITANCE_ERROR ;
645
660
ZEND_TYPE_FOREACH (fe_type , single_type ) {
646
- inheritance_status status ;
647
- zend_string * fe_class_name ;
648
- zend_class_entry * fe_ce = NULL ;
649
-
650
- if (ZEND_TYPE_HAS_NAME (* single_type )) {
651
- fe_class_name = resolve_class_name (fe_scope , ZEND_TYPE_NAME (* single_type ));
652
- } else if (ZEND_TYPE_HAS_CE (* single_type )) {
653
- fe_ce = ZEND_TYPE_CE (* single_type );
654
- fe_class_name = fe_ce -> name ;
655
- } else {
661
+ zend_class_entry * fe_ce ;
662
+ zend_string * fe_class_name = get_class_from_type (& fe_ce , fe_scope , * single_type );
663
+ if (!fe_class_name ) {
656
664
continue ;
657
665
}
658
666
659
- status = zend_is_class_subtype_of_type (
660
- fe_scope , fe_class_name , fe_ce , proto_scope , proto_type ,
661
- /* register_unresolved */ false);
667
+ inheritance_status status = zend_is_class_subtype_of_type (
668
+ fe_scope , fe_class_name , fe_ce , proto_scope , proto_type );
662
669
if (status == early_exit_status ) {
663
670
return early_exit_status ;
664
671
}
0 commit comments