Skip to content

Commit 6836b10

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 c211319 commit 6836b10

File tree

1 file changed

+27
-73
lines changed

1 file changed

+27
-73
lines changed

Zend/zend_inheritance.c

Lines changed: 27 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ static inheritance_status zend_perform_intersection_covariant_class_type_check(
446446
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR;
447447
}
448448

449+
/* Check whether a single class proto type is a subtype of a potentially complex fe_type. */
449450
static inheritance_status zend_perform_covariant_class_type_check(
450451
zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *fe_ce,
451452
zend_class_entry *proto_scope, zend_type proto_type,
@@ -478,15 +479,19 @@ static inheritance_status zend_perform_covariant_class_type_check(
478479
zend_type *single_type;
479480

480481
/* Traverse the list of parent types and check if the current child (FE)
481-
* class is the subtype of at least one of them */
482+
* class is the subtype of at least one of them (union) or all of them (intersection). */
483+
bool is_intersection = ZEND_TYPE_IS_INTERSECTION(proto_type);
482484
ZEND_TYPE_FOREACH(proto_type, single_type) {
483485
zend_class_entry *proto_ce;
484486
zend_string *proto_class_name = NULL;
485487
if (ZEND_TYPE_HAS_NAME(*single_type)) {
486488
proto_class_name =
487489
resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type));
488490
if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
489-
return INHERITANCE_SUCCESS;
491+
if (!is_intersection) {
492+
return INHERITANCE_SUCCESS;
493+
}
494+
continue;
490495
}
491496

492497
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved);
@@ -497,69 +502,31 @@ static inheritance_status zend_perform_covariant_class_type_check(
497502
proto_ce = ZEND_TYPE_CE(*single_type);
498503
} else {
499504
/* standard type */
505+
ZEND_ASSERT(!is_intersection);
500506
continue;
501507
}
502508

503509
if (!fe_ce || !proto_ce) {
504510
have_unresolved = 1;
505-
} else if (unlinked_instanceof(fe_ce, proto_ce)) {
511+
continue;
512+
}
513+
if (unlinked_instanceof(fe_ce, proto_ce)) {
506514
track_class_dependency(fe_ce, fe_class_name);
507515
track_class_dependency(proto_ce, proto_class_name);
508-
return INHERITANCE_SUCCESS;
509-
}
510-
} ZEND_TYPE_FOREACH_END();
511-
512-
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR;
513-
}
514-
515-
/* checks that the child type (being unique) is a subtype of each member of the parent intersection */
516-
static inheritance_status zend_is_single_type_subtype_intersection(
517-
zend_class_entry *fe_scope, zend_string *fe_class_name,
518-
zend_class_entry *fe_ce, zend_class_entry *proto_scope,
519-
zend_type proto_type, bool register_unresolved
520-
) {
521-
bool have_unresolved = false;
522-
zend_type *single_type;
523-
zend_type_list *parent_intersection_types;
524-
525-
ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(proto_type));
526-
527-
parent_intersection_types = ZEND_TYPE_LIST(proto_type);
528-
529-
ZEND_TYPE_LIST_FOREACH(parent_intersection_types, single_type) {
530-
zend_class_entry *proto_ce;
531-
zend_string *proto_class_name = NULL;
532-
if (ZEND_TYPE_HAS_NAME(*single_type)) {
533-
proto_class_name =
534-
resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type));
535-
if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
536-
continue;
516+
if (!is_intersection) {
517+
return INHERITANCE_SUCCESS;
537518
}
538-
539-
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved);
540-
proto_ce = lookup_class(proto_scope, proto_class_name, register_unresolved);
541-
} else if (ZEND_TYPE_HAS_CE(*single_type)) {
542-
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved);
543-
proto_ce = ZEND_TYPE_CE(*single_type);
544519
} else {
545-
/* standard type cannot be part a subtype of an intersection type */
546-
ZEND_UNREACHABLE();
547-
continue;
548-
}
549-
550-
if (!fe_ce || !proto_ce) {
551-
have_unresolved = true;
552-
continue;
553-
}
554-
if (!unlinked_instanceof(fe_ce, proto_ce)) {
555-
return INHERITANCE_ERROR;
520+
if (is_intersection) {
521+
return INHERITANCE_ERROR;
522+
}
556523
}
524+
} ZEND_TYPE_FOREACH_END();
557525

558-
track_class_dependency(fe_ce, fe_class_name);
559-
track_class_dependency(proto_ce, proto_class_name);
560-
} ZEND_TYPE_LIST_FOREACH_END();
561-
562-
return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_SUCCESS;
526+
if (have_unresolved) {
527+
return INHERITANCE_UNRESOLVED;
528+
}
529+
return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
563530
}
564531

565532
static inheritance_status zend_perform_covariant_type_check(
@@ -682,16 +649,9 @@ static inheritance_status zend_perform_covariant_type_check(
682649
continue;
683650
}
684651

685-
if (UNEXPECTED(ZEND_TYPE_IS_INTERSECTION(proto_type))) {
686-
status = zend_is_single_type_subtype_intersection(fe_scope,
687-
fe_class_name, fe_ce, proto_scope, proto_type,
688-
/* register_unresolved */ false);
689-
} else {
690-
status = zend_perform_covariant_class_type_check(fe_scope,
691-
fe_class_name, fe_ce, proto_scope, proto_type,
692-
/* register_unresolved */ false);
693-
}
694-
652+
status = zend_perform_covariant_class_type_check(fe_scope,
653+
fe_class_name, fe_ce, proto_scope, proto_type,
654+
/* register_unresolved */ false);
695655
if (status == INHERITANCE_ERROR) {
696656
return INHERITANCE_ERROR;
697657
}
@@ -741,15 +701,9 @@ static inheritance_status zend_perform_covariant_type_check(
741701
continue;
742702
}
743703

744-
if (UNEXPECTED(ZEND_TYPE_IS_INTERSECTION(proto_type))) {
745-
zend_is_single_type_subtype_intersection(fe_scope,
746-
fe_class_name, fe_ce, proto_scope, proto_type,
747-
/* register_unresolved */ true);
748-
} else {
749-
zend_perform_covariant_class_type_check(fe_scope,
750-
fe_class_name, fe_ce, proto_scope, proto_type,
751-
/* register_unresolved */ true);
752-
}
704+
zend_perform_covariant_class_type_check(fe_scope,
705+
fe_class_name, fe_ce, proto_scope, proto_type,
706+
/* register_unresolved */ true);
753707
} ZEND_TYPE_FOREACH_END();
754708
}
755709
return INHERITANCE_UNRESOLVED;

0 commit comments

Comments
 (0)