Skip to content

Commit 155350d

Browse files
committed
initial type tree implementation
1 parent 3142193 commit 155350d

File tree

7 files changed

+346
-32
lines changed

7 files changed

+346
-32
lines changed

Zend/zend_API.c

Lines changed: 223 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,7 +2898,223 @@ ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, z
28982898
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arg_info_toString, 0, 0, IS_STRING, 0)
28992899
ZEND_END_ARG_INFO()
29002900

2901-
static zend_always_inline void zend_normalize_internal_type(zend_type *type) {
2901+
static HashTable *interned_type_tree = NULL;
2902+
2903+
// todo: move to zend_types.h
2904+
#define ADD_TO_TREE(list, count, value) \
2905+
do { \
2906+
list = erealloc(list, sizeof(zend_type) * (count + 1)); \
2907+
list[count++] = value; \
2908+
} while (0)
2909+
2910+
static int compare_simple_types(zend_type a, zend_type b) {
2911+
uint32_t a_mask = ZEND_TYPE_FULL_MASK(a);
2912+
uint32_t b_mask = ZEND_TYPE_FULL_MASK(b);
2913+
2914+
if (a_mask != b_mask) {
2915+
return a_mask < b_mask ? -1 : 1;
2916+
}
2917+
2918+
bool a_has_name = ZEND_TYPE_HAS_NAME(a);
2919+
bool b_has_name = ZEND_TYPE_HAS_NAME(b);
2920+
2921+
if (a_has_name && b_has_name) {
2922+
zend_string *a_name = ZEND_TYPE_NAME(a);
2923+
zend_string *b_name = ZEND_TYPE_NAME(b);
2924+
int cmp = ZSTR_VAL(a_name) == ZSTR_VAL(b_name);
2925+
if (cmp != 0) {
2926+
return cmp;
2927+
}
2928+
}
2929+
2930+
bool a_nullable = ZEND_TYPE_ALLOW_NULL(a);
2931+
bool b_nullable = ZEND_TYPE_ALLOW_NULL(b);
2932+
2933+
if (a_nullable != b_nullable) {
2934+
return a_nullable ? 1 : -1;
2935+
}
2936+
2937+
// Types are equal
2938+
return 0;
2939+
}
2940+
2941+
static int compare_type_nodes(const void *a_, const void *b_) {
2942+
zend_type_node *a = *(zend_type_node **)a_;
2943+
zend_type_node *b = *(zend_type_node **)b_;
2944+
2945+
if (a->kind != b->kind) {
2946+
return a->kind - b->kind;
2947+
}
2948+
2949+
if (a->kind == ZEND_TYPE_SIMPLE) {
2950+
return compare_simple_types(a->simple_type, b->simple_type);
2951+
}
2952+
2953+
if (a->compound.num_types != b->compound.num_types) {
2954+
return (int)a->compound.num_types - (int)b->compound.num_types;
2955+
}
2956+
2957+
for (uint32_t i = 0; i < a->compound.num_types; i++) {
2958+
const int cmp = compare_type_nodes(&a->compound.types[i], &b->compound.types[i]);
2959+
if (cmp != 0) {
2960+
return cmp;
2961+
}
2962+
}
2963+
2964+
return 0;
2965+
}
2966+
2967+
zend_ulong zend_type_node_hash(zend_type_node *node) {
2968+
zend_ulong hash = 2166136261u; // FNV-1a offset basis
2969+
2970+
hash ^= (zend_ulong)node->kind;
2971+
hash *= 16777619;
2972+
2973+
switch (node->kind) {
2974+
case ZEND_TYPE_SIMPLE: {
2975+
zend_type type = node->simple_type;
2976+
hash ^= (zend_ulong)ZEND_TYPE_FULL_MASK(type);
2977+
hash *= 16777619;
2978+
2979+
if (ZEND_TYPE_HAS_NAME(type)) {
2980+
zend_string *name = ZEND_TYPE_NAME(type);
2981+
hash ^= zend_string_hash_val(name);
2982+
hash *= 16777619;
2983+
}
2984+
2985+
break;
2986+
}
2987+
2988+
case ZEND_TYPE_UNION:
2989+
case ZEND_TYPE_INTERSECTION: {
2990+
for (uint32_t i = 0; i < node->compound.num_types; ++i) {
2991+
zend_ulong child_hash = zend_type_node_hash(node->compound.types[i]);
2992+
hash ^= child_hash;
2993+
hash *= 16777619;
2994+
}
2995+
break;
2996+
}
2997+
}
2998+
2999+
return hash;
3000+
}
3001+
3002+
bool zend_type_node_equals(zend_type_node *a, zend_type_node *b) {
3003+
if (a == b) return true;
3004+
if (a->kind != b->kind) return false;
3005+
3006+
if (a->kind == ZEND_TYPE_SIMPLE) {
3007+
zend_type at = a->simple_type;
3008+
zend_type bt = b->simple_type;
3009+
3010+
if (ZEND_TYPE_FULL_MASK(at) != ZEND_TYPE_FULL_MASK(bt)) {
3011+
return false;
3012+
}
3013+
3014+
bool a_has_name = ZEND_TYPE_HAS_NAME(at);
3015+
bool b_has_name = ZEND_TYPE_HAS_NAME(bt);
3016+
if (a_has_name != b_has_name) {
3017+
return false;
3018+
}
3019+
3020+
if (a_has_name) {
3021+
zend_string *a_name = ZEND_TYPE_NAME(at);
3022+
zend_string *b_name = ZEND_TYPE_NAME(bt);
3023+
if (!zend_string_equals(a_name, b_name)) {
3024+
return false;
3025+
}
3026+
}
3027+
3028+
return true;
3029+
}
3030+
3031+
// Compound type: union or intersection
3032+
if (a->compound.num_types != b->compound.num_types) {
3033+
return false;
3034+
}
3035+
3036+
for (uint32_t i = 0; i < a->compound.num_types; ++i) {
3037+
if (!zend_type_node_equals(a->compound.types[i], b->compound.types[i])) {
3038+
return false;
3039+
}
3040+
}
3041+
3042+
return true;
3043+
}
3044+
3045+
3046+
static zend_type_node *intern_type_node(zend_type_node *node) {
3047+
zend_ulong hash = zend_type_node_hash(node);
3048+
zend_type_node *existing;
3049+
3050+
if (interned_type_tree == NULL) {
3051+
interned_type_tree = pemalloc(sizeof(HashTable), 1);
3052+
zend_hash_init(interned_type_tree, 64, NULL, NULL, 1);
3053+
}
3054+
3055+
if ((existing = zend_hash_index_find_ptr(interned_type_tree, hash))) {
3056+
if (zend_type_node_equals(existing, node)) {
3057+
return existing; // reuse interned node
3058+
}
3059+
}
3060+
3061+
zend_hash_index_add_new_ptr(interned_type_tree, hash, node);
3062+
return node;
3063+
}
3064+
3065+
3066+
ZEND_API zend_type_node *zend_type_to_interned_tree(zend_type type) {
3067+
if (type.type_mask == 0) {
3068+
return NULL;
3069+
}
3070+
3071+
if (!ZEND_TYPE_HAS_LIST(type)) {
3072+
zend_type_node *node = pemalloc(sizeof(zend_type_node), 1);
3073+
node->kind = ZEND_TYPE_SIMPLE;
3074+
node->simple_type = type;
3075+
return intern_type_node(node);
3076+
}
3077+
3078+
zend_type_list *list = ZEND_TYPE_LIST(type);
3079+
zend_type_node_kind kind = ZEND_TYPE_IS_INTERSECTION(type) ?
3080+
ZEND_TYPE_INTERSECTION : ZEND_TYPE_UNION;
3081+
3082+
zend_type_node **children = NULL;
3083+
uint32_t num_children = 0;
3084+
3085+
zend_type *subtype;
3086+
3087+
ZEND_TYPE_LIST_FOREACH(list, subtype) {
3088+
zend_type_node *child = zend_type_to_interned_tree(*subtype);
3089+
3090+
if (child->kind == kind) {
3091+
for (uint32_t i = 0; child->compound.num_types; i++) {
3092+
ADD_TO_TREE(children, num_children, child->compound.types[i]);
3093+
}
3094+
} else {
3095+
ADD_TO_TREE(children, num_children, child);
3096+
}
3097+
} ZEND_TYPE_LIST_FOREACH_END();
3098+
3099+
qsort(children, num_children, sizeof(zend_type_node*), compare_type_nodes);
3100+
3101+
size_t deduped_count = 0;
3102+
for (size_t i = 0; i < num_children; i++) {
3103+
if (i == 0 || compare_type_nodes(&children[i], &children[i - 1]) != 0) {
3104+
children[deduped_count++] = children[i];
3105+
}
3106+
}
3107+
3108+
zend_type_node *node = pemalloc(sizeof(zend_type_node), 1);
3109+
node->kind = kind;
3110+
node->compound.num_types = deduped_count;
3111+
node->compound.types = pemalloc(sizeof(zend_type_node *) * deduped_count, 1);
3112+
memcpy(node->compound.types, children, sizeof(zend_type_node *) * deduped_count);
3113+
3114+
return intern_type_node(node);
3115+
}
3116+
3117+
static zend_always_inline zend_type_node *zend_normalize_internal_type(zend_type *type) {
29023118
ZEND_ASSERT(!ZEND_TYPE_HAS_LITERAL_NAME(*type));
29033119
if (ZEND_TYPE_PURE_MASK(*type) != MAY_BE_ANY) {
29043120
ZEND_ASSERT(!ZEND_TYPE_CONTAINS_CODE(*type, IS_RESOURCE) && "resource is not allowed in a zend_type");
@@ -2921,6 +3137,8 @@ static zend_always_inline void zend_normalize_internal_type(zend_type *type) {
29213137
} ZEND_TYPE_FOREACH_END();
29223138
}
29233139
} ZEND_TYPE_FOREACH_END();
3140+
3141+
return zend_type_to_interned_tree(*type);
29243142
}
29253143

29263144
/* registers all functions in *library_functions in the function hash */
@@ -3190,7 +3408,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
31903408
new_arg_info[i].type = legacy_iterable;
31913409
}
31923410

3193-
zend_normalize_internal_type(&new_arg_info[i].type);
3411+
new_arg_info[i].type_tree = zend_normalize_internal_type(&new_arg_info[i].type);
31943412
}
31953413
}
31963414

@@ -4665,7 +4883,9 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z
46654883
property_info->type = type;
46664884

46674885
if (is_persistent_class(ce)) {
4668-
zend_normalize_internal_type(&property_info->type);
4886+
property_info->type_tree = zend_normalize_internal_type(&property_info->type);
4887+
} else {
4888+
property_info->type_tree = zend_type_to_interned_tree(property_info->type);
46694889
}
46704890

46714891
zend_hash_update_ptr(&ce->properties_info, name, property_info);

Zend/zend_API.h

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -128,46 +128,46 @@ typedef struct _zend_fcall_info_cache {
128128

129129
/* Arginfo structures without type information */
130130
#define ZEND_ARG_INFO(pass_by_ref, name) \
131-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
131+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, NULL },
132132
#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \
133-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
133+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, default_value },
134134
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
135-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
135+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL, NULL },
136136

137137
/* Arginfo structures with simple type information */
138138
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
139-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
139+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, NULL },
140140
#define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \
141-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
141+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, default_value },
142142
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
143-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
143+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL, NULL },
144144

145145
/* Arginfo structures with complex type information */
146146
#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \
147-
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
147+
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, default_value },
148148
#define ZEND_ARG_OBJ_TYPE_MASK(pass_by_ref, name, class_name, type_mask, default_value) \
149-
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
149+
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, default_value },
150150
#define ZEND_ARG_VARIADIC_OBJ_TYPE_MASK(pass_by_ref, name, class_name, type_mask) \
151-
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
151+
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL, NULL },
152152

153153
/* Arginfo structures with object type information */
154154
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, class_name, allow_null) \
155-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
155+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, NULL },
156156
#define ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, class_name, allow_null, default_value) \
157-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
157+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, default_value },
158158
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, class_name, allow_null) \
159-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
159+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL, NULL },
160160

161161
/* Legacy arginfo structures */
162162
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \
163-
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
163+
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, NULL },
164164
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \
165-
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
165+
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL, NULL },
166166

167167
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, is_tentative_return_type) \
168168
static const zend_internal_arg_info name[] = { \
169169
{ (const char*)(uintptr_t)(required_num_args), \
170-
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
170+
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL, NULL },
171171

172172
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
173173
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, 0)
@@ -180,7 +180,7 @@ typedef struct _zend_fcall_info_cache {
180180

181181
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, is_tentative_return_type) \
182182
static const zend_internal_arg_info name[] = { \
183-
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
183+
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL, NULL },
184184

185185
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
186186
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, 0)
@@ -190,7 +190,7 @@ typedef struct _zend_fcall_info_cache {
190190

191191
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, is_tentative_return_type) \
192192
static const zend_internal_arg_info name[] = { \
193-
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
193+
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL, NULL },
194194

195195
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
196196
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, 0)
@@ -200,7 +200,7 @@ typedef struct _zend_fcall_info_cache {
200200

201201
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, is_tentative_return_type) \
202202
static const zend_internal_arg_info name[] = { \
203-
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
203+
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL, NULL },
204204

205205
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
206206
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, 0)
@@ -213,7 +213,7 @@ typedef struct _zend_fcall_info_cache {
213213

214214
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
215215
static const zend_internal_arg_info name[] = { \
216-
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0, 0)), NULL },
216+
{ (const char*)(uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0, 0)), NULL, NULL },
217217
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
218218
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
219219
#define ZEND_END_ARG_INFO() };
@@ -448,6 +448,8 @@ ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const ze
448448
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type);
449449
ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type);
450450

451+
ZEND_API zend_type_node *zend_type_to_interned_tree(zend_type type);
452+
451453
static zend_always_inline HashTable *zend_class_constants_table(zend_class_entry *ce) {
452454
if ((ce->ce_flags & ZEND_ACC_HAS_AST_CONSTANTS) && ZEND_MAP_PTR(ce->mutable_data)) {
453455
zend_class_mutable_data *mutable_data =

Zend/zend_compile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7348,6 +7348,7 @@ static zend_type zend_compile_typename_ex(
73487348
}
73497349

73507350
ast->attr = orig_ast_attr;
7351+
73517352
return type;
73527353
}
73537354
/* }}} */
@@ -7584,6 +7585,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
75847585
} else {
75857586
arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
75867587
}
7588+
arg_infos->type_tree = zend_type_to_interned_tree(arg_infos->type);
75877589
arg_infos++;
75887590
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
75897591

@@ -7830,6 +7832,8 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
78307832
&prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, ZEND_ATTRIBUTE_TARGET_PARAMETER);
78317833
}
78327834
}
7835+
7836+
arg_info->type_tree = zend_type_to_interned_tree(arg_info->type);
78337837
}
78347838

78357839
/* These are assigned at the end to avoid uninitialized memory in case of an error */

0 commit comments

Comments
 (0)