Skip to content

Commit 873f7a0

Browse files
committed
W.I.P. cannot figure out bound types right now
1 parent 5646482 commit 873f7a0

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

Zend/zend_execute.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,23 +1149,76 @@ static bool zend_check_intersection_type_from_list(
11491149
return true;
11501150
}
11511151

1152+
static bool zend_type_is_equal(zend_type given_type, zend_type constraint_type) {
1153+
if (ZEND_TYPE_PURE_MASK(given_type) != ZEND_TYPE_PURE_MASK(constraint_type)) {
1154+
return false;
1155+
}
1156+
if (ZEND_TYPE_HAS_NAME(given_type)) {
1157+
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(constraint_type));
1158+
return zend_string_equals(ZEND_TYPE_NAME(given_type), ZEND_TYPE_NAME(constraint_type));
1159+
} else if (ZEND_TYPE_HAS_LIST(given_type)) {
1160+
ZEND_ASSERT(ZEND_TYPE_HAS_LIST(constraint_type));
1161+
const zend_type_list *given_list_type = ZEND_TYPE_LIST(given_type);
1162+
const zend_type_list *constraint_list_type = ZEND_TYPE_LIST(constraint_type);
1163+
for (uint32_t list_type_index = 0; list_type_index < given_list_type->num_types; list_type_index++) {
1164+
zend_type inner_given_type = given_list_type->types[list_type_index];
1165+
zend_type inner_constraint_type = constraint_list_type->types[list_type_index];
1166+
if (!zend_type_is_equal(inner_given_type, inner_constraint_type)) {
1167+
return false;
1168+
}
1169+
}
1170+
return true;
1171+
}
1172+
return true;
1173+
}
1174+
11521175
static zend_always_inline bool zend_check_type_slow(
11531176
const zend_type *type, zval *arg, const zend_reference *ref,
11541177
bool is_return_type, bool is_internal)
11551178
{
11561179
if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
1157-
zend_class_entry *ce;
1180+
const zend_class_entry *ce;
11581181
if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) {
1159-
if (ZEND_TYPE_IS_INTERSECTION(*type)) {
1182+
if (ZEND_TYPE_IS_NAME_WITH_GENERIC_TYPES(*type)) {
1183+
uint32_t inner_type = 0;
1184+
bool is_ce = true;
1185+
const HashTable *bound_generic_types = NULL;
1186+
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), const zend_type *list_type) {
1187+
if (is_ce) {
1188+
is_ce = false;
1189+
ce = zend_fetch_ce_from_type(list_type);
1190+
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
1191+
return false;
1192+
}
1193+
// TODO: bound_generic_types is null
1194+
bound_generic_types = zend_hash_find_ptr_lc(Z_OBJCE_P(arg)->bound_types, ce->name);
1195+
if (!bound_generic_types
1196+
|| zend_hash_num_elements(bound_generic_types) != ce->num_generic_parameters
1197+
/* -1 because the class name must be excluded */
1198+
|| zend_hash_num_elements(bound_generic_types) != ZEND_TYPE_LIST(*type)->num_types-1
1199+
) {
1200+
return false;
1201+
}
1202+
continue;
1203+
}
1204+
ZEND_ASSERT(ce);
1205+
ZEND_ASSERT(bound_generic_types);
1206+
const zend_type *bound_type = zend_hash_index_find_ptr(bound_generic_types, inner_type++);
1207+
ZEND_ASSERT(bound_type);
1208+
if (!zend_type_is_equal(*list_type, *bound_type)) {
1209+
return false;
1210+
}
1211+
} ZEND_TYPE_LIST_FOREACH_END();
1212+
} else if (ZEND_TYPE_IS_INTERSECTION(*type)) {
11601213
return zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg));
11611214
} else {
1162-
const zend_type *list_type;
1163-
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1215+
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), const zend_type *list_type) {
11641216
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
11651217
if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) {
11661218
return true;
11671219
}
11681220
} else {
1221+
/* TODO: Handle generic, or is this actually prevented ? */
11691222
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
11701223
ce = zend_fetch_ce_from_type(list_type);
11711224
/* Instance of a single type part of a union is sufficient to pass the type check */

Zend/zend_inheritance.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,7 @@ ZEND_ATTRIBUTE_NONNULL static void bind_generic_types_for_inherited_interfaces(z
23962396
}
23972397
const zend_type t1 = *iface_bound_type_ptr;
23982398
const zend_type t2 = *ce_bound_type_ptr;
2399+
// TODO Use zend_types_equals()
23992400
if (
24002401
ZEND_TYPE_FULL_MASK(t1) != ZEND_TYPE_FULL_MASK(t2)
24012402
|| (ZEND_TYPE_HAS_NAME(t1) && !zend_string_equals(ZEND_TYPE_NAME(t1), ZEND_TYPE_NAME(t2)))

0 commit comments

Comments
 (0)