Skip to content

Commit fe7c270

Browse files
committed
Merge zend_is_single_type_subtype_intersection() function
Make zend_perform_intersection_covariant_class_type_check() a single function that checks whether a simple type is a subtype of a complex type.
1 parent 2b026cc commit fe7c270

File tree

1 file changed

+24
-64
lines changed

1 file changed

+24
-64
lines changed

Zend/zend_inheritance.c

Lines changed: 24 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ static inheritance_status zend_perform_intersection_covariant_class_type_check(
450450
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR;
451451
}
452452

453+
/* Check whether a single class proto type is a subtype of a potentially complex fe_type. */
453454
static inheritance_status zend_perform_covariant_class_type_check(
454455
zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *fe_ce,
455456
zend_class_entry *proto_scope, zend_type proto_type) {
@@ -481,15 +482,19 @@ static inheritance_status zend_perform_covariant_class_type_check(
481482
zend_type *single_type;
482483

483484
/* 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);
485487
ZEND_TYPE_FOREACH(proto_type, single_type) {
486488
zend_class_entry *proto_ce;
487489
zend_string *proto_class_name = NULL;
488490
if (ZEND_TYPE_HAS_NAME(*single_type)) {
489491
proto_class_name =
490492
resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type));
491493
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;
493498
}
494499

495500
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(
499504
proto_ce = ZEND_TYPE_CE(*single_type);
500505
} else {
501506
/* standard type */
507+
ZEND_ASSERT(!is_intersection);
502508
continue;
503509
}
504510

505511
if (!fe_ce || !proto_ce) {
506512
have_unresolved = 1;
507-
} else if (unlinked_instanceof(fe_ce, proto_ce)) {
513+
continue;
514+
}
515+
if (unlinked_instanceof(fe_ce, proto_ce)) {
508516
track_class_dependency(fe_ce, fe_class_name);
509517
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;
539520
}
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);
546521
} 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+
}
558525
}
526+
} ZEND_TYPE_FOREACH_END();
559527

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;
565532
}
566533

567534
static void register_unresolved_classes(zend_class_entry *scope, zend_type type) {
@@ -694,16 +661,9 @@ static inheritance_status zend_perform_covariant_type_check(
694661
continue;
695662
}
696663

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);
707667
if (status == INHERITANCE_ERROR) {
708668
return INHERITANCE_ERROR;
709669
}

0 commit comments

Comments
 (0)