Skip to content

Commit a2e21e4

Browse files
committed
initial type tree implementation
1 parent 68f5063 commit a2e21e4

9 files changed

+352
-38
lines changed

Zend/zend_API.c

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

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

29473165
/* registers all functions in *library_functions in the function hash */
@@ -3211,7 +3429,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
32113429
new_arg_info[i].type = legacy_iterable;
32123430
}
32133431

3214-
zend_normalize_internal_type(&new_arg_info[i].type);
3432+
new_arg_info[i].type_tree = zend_normalize_internal_type(&new_arg_info[i].type);
32153433
}
32163434
}
32173435

@@ -4686,7 +4904,9 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z
46864904
property_info->type = type;
46874905

46884906
if (is_persistent_class(ce)) {
4689-
zend_normalize_internal_type(&property_info->type);
4907+
property_info->type_tree = zend_normalize_internal_type(&property_info->type);
4908+
} else {
4909+
property_info->type_tree = zend_type_to_interned_tree(property_info->type);
46904910
}
46914911

46924912
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
@@ -7417,6 +7417,7 @@ static zend_type zend_compile_typename_ex(
74177417
}
74187418

74197419
ast->attr = orig_ast_attr;
7420+
74207421
return type;
74217422
}
74227423
/* }}} */
@@ -7653,6 +7654,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
76537654
} else {
76547655
arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
76557656
}
7657+
arg_infos->type_tree = zend_type_to_interned_tree(arg_infos->type);
76567658
arg_infos++;
76577659
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
76587660

@@ -7899,6 +7901,8 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
78997901
&prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, ZEND_ATTRIBUTE_TARGET_PARAMETER);
79007902
}
79017903
}
7904+
7905+
arg_info->type_tree = zend_type_to_interned_tree(arg_info->type);
79027906
}
79037907

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

0 commit comments

Comments
 (0)