Skip to content

Commit 6194356

Browse files
committed
Associate type to CE and minimal duplicate check
1 parent a95179e commit 6194356

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

Zend/tests/type_declarations/associated/repeated_associated_type.phpt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
--TEST--
2-
Associated types basic
2+
Repeated associated type
33
--FILE--
44
<?php
55

66
interface I {
7+
type T;
78
type T;
89
public function foo(T $param): T;
910
}
@@ -14,4 +15,4 @@ class C implements I {
1415

1516
?>
1617
--EXPECTF--
17-
Parse error: syntax error, unexpected token "type", expecting "function" in %s on line %d
18+
Fatal error: Cannot have two associated types with the same name "T" in %s on line %d

Zend/zend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ struct _zend_class_entry {
218218
zend_trait_precedence **trait_precedences;
219219
HashTable *attributes;
220220

221+
/* Only for interfaces */
222+
HashTable *associated_types;
223+
221224
uint32_t enum_backing_type;
222225
HashTable *backed_enum_table;
223226

Zend/zend_compile.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_hand
20722072
ce->default_static_members_count = 0;
20732073
ce->properties_info_table = NULL;
20742074
ce->attributes = NULL;
2075+
ce->associated_types = NULL;
20752076
ce->enum_backing_type = IS_UNDEF;
20762077
ce->backed_enum_table = NULL;
20772078

@@ -9020,18 +9021,33 @@ static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
90209021
}
90219022
/* }}} */
90229023

9024+
9025+
90239026
static void zend_compile_associated_type(zend_ast *ast) {
90249027
zend_class_entry *ce = CG(active_class_entry);
9028+
HashTable *associated_types = ce->associated_types;
9029+
zend_ast *name_ast = ast->child[0];
9030+
zend_string *name = zend_ast_get_str(name_ast);
90259031

90269032
if ((ce->ce_flags & ZEND_ACC_INTERFACE) == 0) {
90279033
zend_error_noreturn(E_COMPILE_ERROR,
90289034
"Cannot use associated types outside of interfaces, used in %s", ZSTR_VAL(ce->name));
90299035
}
90309036

9031-
zend_ast *name_ast = ast->child[0];
9032-
zend_string *name = zend_ast_get_str(name_ast);
90339037
ZEND_ASSERT(name != NULL);
9034-
// TODO add associated type to CE
9038+
bool persistent = false; // TODO I need to figure this out
9039+
if (associated_types == NULL) {
9040+
ce->associated_types = pemalloc(sizeof(HashTable), persistent);
9041+
zend_hash_init(ce->associated_types, 8, NULL, NULL, persistent);
9042+
associated_types = ce->associated_types;
9043+
}
9044+
if (zend_hash_exists(associated_types, name)) {
9045+
zend_error_noreturn(E_COMPILE_ERROR,
9046+
"Cannot have two associated types with the same name \"%s\"", ZSTR_VAL(name));
9047+
}
9048+
zval tmp;
9049+
ZVAL_UNDEF(&tmp);
9050+
zend_hash_add_new(associated_types, name, &tmp);
90359051
}
90369052

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

Zend/zend_opcode.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ ZEND_API void destroy_zend_class(zval *zv)
351351
zend_hash_release(ce->attributes);
352352
}
353353

354+
if (ce->associated_types) {
355+
zend_hash_release(ce->associated_types);
356+
}
357+
354358
if (ce->num_interfaces > 0 && !(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
355359
uint32_t i;
356360

@@ -527,6 +531,9 @@ ZEND_API void destroy_zend_class(zval *zv)
527531
if (ce->attributes) {
528532
zend_hash_release(ce->attributes);
529533
}
534+
if (ce->associated_types) {
535+
zend_hash_release(ce->associated_types);
536+
}
530537
free(ce);
531538
break;
532539
}

0 commit comments

Comments
 (0)