Skip to content

Commit 263f12a

Browse files
committed
Use zend_strings instead of HT
1 parent 2e48282 commit 263f12a

File tree

5 files changed

+61
-19
lines changed

5 files changed

+61
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Multiple associated types
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
type K;
8+
type V;
9+
public function set(K $key, V $value): void;
10+
public function get(K $key): V;
11+
}
12+
13+
class C implements I {
14+
public function set(int $key, string $value): void {}
15+
public function get(int $key): string {}
16+
}
17+
18+
?>
19+
--EXPECTF--
20+
Fatal error: Declaration of C::set(int $key, string $value): void must be compatible with I::set(K $key, V $value): void in %s on line %d

Diff for: Zend/zend.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ struct _zend_class_entry {
219219
HashTable *attributes;
220220

221221
/* Only for interfaces */
222-
HashTable *associated_types;
222+
zend_string **associated_types;
223+
uint32_t num_associated_types;
223224

224225
uint32_t enum_backing_type;
225226
HashTable *backed_enum_table;

Diff for: Zend/zend_compile.c

+28-14
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_hand
20732073
ce->properties_info_table = NULL;
20742074
ce->attributes = NULL;
20752075
ce->associated_types = NULL;
2076+
ce->num_associated_types = 0;
20762077
ce->enum_backing_type = IS_UNDEF;
20772078
ce->backed_enum_table = NULL;
20782079

@@ -7005,8 +7006,14 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
70057006
if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
70067007
class_name = zend_resolve_class_name_ast(ast);
70077008
zend_assert_valid_class_name(class_name, "a type name");
7008-
if (ce && ce->associated_types && zend_hash_exists(ce->associated_types, class_name)) {
7009-
flags = _ZEND_TYPE_ASSOCIATED_BIT;
7009+
if (ce && ce->associated_types) {
7010+
for (uint32_t i = 0; i < ce->num_associated_types; i++) {
7011+
const zend_string *cur = ce->associated_types[i];
7012+
if (zend_string_equals(class_name, cur)) {
7013+
flags = _ZEND_TYPE_ASSOCIATED_BIT;
7014+
break;
7015+
}
7016+
}
70107017
}
70117018
} else {
70127019
ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT);
@@ -9035,9 +9042,9 @@ static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
90359042

90369043

90379044

9038-
static void zend_compile_associated_type(zend_ast *ast) {
9045+
static void zend_compile_associated_type(const zend_ast *ast) {
90399046
zend_class_entry *ce = CG(active_class_entry);
9040-
HashTable *associated_types = ce->associated_types;
9047+
zend_string **associated_types = ce->associated_types;
90419048
zend_ast *name_ast = ast->child[0];
90429049
zend_string *name = zend_ast_get_str(name_ast);
90439050

@@ -9047,19 +9054,26 @@ static void zend_compile_associated_type(zend_ast *ast) {
90479054
}
90489055

90499056
ZEND_ASSERT(name != NULL);
9050-
bool persistent = false; // TODO I need to figure this out
9057+
// TODO This is very jank
9058+
const bool persistent = ce->type == ZEND_INTERNAL_CLASS;
90519059
if (associated_types == NULL) {
9052-
ce->associated_types = pemalloc(sizeof(HashTable), persistent);
9053-
zend_hash_init(ce->associated_types, 8, NULL, NULL, persistent);
9054-
associated_types = ce->associated_types;
9060+
ce->associated_types = pemalloc(sizeof(zend_string*), persistent);
9061+
ce->associated_types[0] = zend_string_copy(name);
9062+
ce->num_associated_types = 1;
9063+
return;
90559064
}
9056-
if (zend_hash_exists(associated_types, name)) {
9057-
zend_error_noreturn(E_COMPILE_ERROR,
9058-
"Cannot have two associated types with the same name \"%s\"", ZSTR_VAL(name));
9065+
for (uint32_t i = 0; i < ce->num_associated_types; i++) {
9066+
const zend_string *cur = ce->associated_types[i];
9067+
if (zend_string_equals(name, cur)) {
9068+
zend_error_noreturn(E_COMPILE_ERROR,
9069+
"Cannot have two associated types with the same name \"%s\"", ZSTR_VAL(name));
9070+
return;
9071+
}
90599072
}
9060-
zval tmp;
9061-
ZVAL_UNDEF(&tmp);
9062-
zend_hash_add_new(associated_types, name, &tmp);
9073+
uint32_t new_size = ce->num_associated_types + 1;
9074+
ce->associated_types = perealloc(ce->associated_types, new_size * sizeof(zend_string*), persistent);
9075+
ce->associated_types[ce->num_associated_types] = zend_string_copy(name);
9076+
ce->num_associated_types = new_size;
90639077
}
90649078

90659079
static void zend_compile_implements(zend_ast *ast) /* {{{ */

Diff for: Zend/zend_inheritance.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ ZEND_API inheritance_status zend_perform_covariant_type_check(
708708

709709
if (ZEND_TYPE_IS_ASSOCIATED(proto_type)) {
710710
return zend_is_type_subtype_of_associated_type(
711-
fe_scope, fe_type_ptr, proto_type_ptr, proto_scope->associated_types);
711+
fe_scope, fe_type_ptr, proto_type_ptr, NULL);
712712
}
713713

714714
/* Builtin types may be removed, but not added */

Diff for: Zend/zend_opcode.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,10 @@ ZEND_API void destroy_zend_class(zval *zv)
352352
}
353353

354354
if (ce->associated_types) {
355-
zend_hash_release(ce->associated_types);
355+
for (uint32_t i = 0; i < ce->num_associated_types; i++) {
356+
zend_string_release(ce->associated_types[i]);
357+
}
358+
efree(ce->associated_types);
356359
}
357360

358361
if (ce->num_interfaces > 0 && !(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
@@ -531,9 +534,13 @@ ZEND_API void destroy_zend_class(zval *zv)
531534
if (ce->attributes) {
532535
zend_hash_release(ce->attributes);
533536
}
534-
if (ce->associated_types) {
535-
zend_hash_release(ce->associated_types);
537+
538+
if (ce->associated_types) {
539+
for (uint32_t i = 0; i < ce->num_associated_types; i++) {
540+
zend_string_release(ce->associated_types[i]);
536541
}
542+
pefree(ce->associated_types, true);
543+
}
537544
free(ce);
538545
break;
539546
}

0 commit comments

Comments
 (0)