Skip to content

Commit dc189f5

Browse files
committedApr 5, 2025
Zend: Add MUTABLE zend_type foreach macros and const qualifiers
The motivation for this is that types should be considered immutable. The only times this is not valid is during compilation, optimizations (opcache), or destruction. Therefore the "normal" type foreach macros are marked to take const arguments and we add mutable version that say so in the name. Thus add various const qualifiers to communicate intent.
1 parent 404059f commit dc189f5

14 files changed

+125
-104
lines changed
 

‎Zend/Optimizer/compact_literals.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static size_t type_num_classes(const zend_op_array *op_array, uint32_t arg_num)
6969
}
7070
ZEND_ASSERT(ZEND_TYPE_IS_UNION(arg_info->type));
7171
size_t count = 0;
72-
zend_type *list_type;
72+
const zend_type *list_type;
7373

7474
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) {
7575
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {

‎Zend/Optimizer/dfa_pass.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
254254
free_alloca(shiftlist, use_heap);
255255
}
256256

257-
static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
257+
static bool safe_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) {
258258
if (ce1 == ce2) {
259259
return 1;
260260
}
@@ -267,9 +267,9 @@ static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
267267

268268
static inline bool can_elide_list_type(
269269
const zend_script *script, const zend_op_array *op_array,
270-
const zend_ssa_var_info *use_info, zend_type type)
270+
const zend_ssa_var_info *use_info, const zend_type type)
271271
{
272-
zend_type *single_type;
272+
const zend_type *single_type;
273273
/* For intersection: result==false is failure, default is success.
274274
* For union: result==true is success, default is failure. */
275275
bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type);
@@ -280,7 +280,7 @@ static inline bool can_elide_list_type(
280280
}
281281
if (ZEND_TYPE_HAS_NAME(*single_type)) {
282282
zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type));
283-
zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname);
283+
const zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname);
284284
zend_string_release(lcname);
285285
bool result = ce && safe_instanceof(use_info->ce, ce);
286286
if (result == !is_intersection) {

‎Zend/zend_API.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2914,14 +2914,14 @@ static zend_always_inline void zend_normalize_internal_type(zend_type *type) {
29142914
ZEND_ASSERT(!ZEND_TYPE_CONTAINS_CODE(*type, IS_RESOURCE) && "resource is not allowed in a zend_type");
29152915
}
29162916
zend_type *current;
2917-
ZEND_TYPE_FOREACH(*type, current) {
2917+
ZEND_TYPE_FOREACH_MUTABLE(*type, current) {
29182918
if (ZEND_TYPE_HAS_NAME(*current)) {
29192919
zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*current));
29202920
zend_alloc_ce_cache(name);
29212921
ZEND_TYPE_SET_PTR(*current, name);
29222922
} else if (ZEND_TYPE_HAS_LIST(*current)) {
29232923
zend_type *inner;
2924-
ZEND_TYPE_FOREACH(*current, inner) {
2924+
ZEND_TYPE_FOREACH_MUTABLE(*current, inner) {
29252925
ZEND_ASSERT(!ZEND_TYPE_HAS_LITERAL_NAME(*inner) && !ZEND_TYPE_HAS_LIST(*inner));
29262926
if (ZEND_TYPE_HAS_NAME(*inner)) {
29272927
zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*inner));

‎Zend/zend_compile.c

+15-15
Original file line numberDiff line numberDiff line change
@@ -1407,10 +1407,10 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop
14071407
}
14081408

14091409
static zend_string *add_intersection_type(zend_string *str,
1410-
zend_type_list *intersection_type_list, zend_class_entry *scope,
1410+
const zend_type_list *intersection_type_list, zend_class_entry *scope,
14111411
bool is_bracketed)
14121412
{
1413-
zend_type *single_type;
1413+
const zend_type *single_type;
14141414
zend_string *intersection_str = NULL;
14151415

14161416
ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) {
@@ -1432,7 +1432,7 @@ static zend_string *add_intersection_type(zend_string *str,
14321432
return str;
14331433
}
14341434

1435-
zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) {
1435+
zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry *scope) {
14361436
zend_string *str = NULL;
14371437

14381438
/* Pure intersection type */
@@ -1441,7 +1441,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
14411441
str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false);
14421442
} else if (ZEND_TYPE_HAS_LIST(type)) {
14431443
/* A union type might not be a list */
1444-
zend_type *list_type;
1444+
const zend_type *list_type;
14451445
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
14461446
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
14471447
str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true);
@@ -1527,7 +1527,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type) {
15271527
return zend_type_to_string_resolved(type, NULL);
15281528
}
15291529

1530-
static bool is_generator_compatible_class_type(zend_string *name) {
1530+
static bool is_generator_compatible_class_type(const zend_string *name) {
15311531
return zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_TRAVERSABLE))
15321532
|| zend_string_equals_literal_ci(name, "Iterator")
15331533
|| zend_string_equals_literal_ci(name, "Generator");
@@ -1541,10 +1541,10 @@ static void zend_mark_function_as_generator(void) /* {{{ */
15411541
}
15421542

15431543
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1544-
zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1544+
const zend_type return_type = CG(active_op_array)->arg_info[-1].type;
15451545
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
15461546
if (!valid_type) {
1547-
zend_type *single_type;
1547+
const zend_type *single_type;
15481548
ZEND_TYPE_FOREACH(return_type, single_type) {
15491549
if (ZEND_TYPE_HAS_NAME(*single_type)
15501550
&& is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) {
@@ -2621,7 +2621,7 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
26212621
/* }}} */
26222622

26232623
/* Remember to update type_num_classes() in compact_literals.c when changing this function */
2624-
static size_t zend_type_get_num_classes(zend_type type) {
2624+
static size_t zend_type_get_num_classes(const zend_type type) {
26252625
if (!ZEND_TYPE_IS_COMPLEX(type)) {
26262626
return 0;
26272627
}
@@ -2632,7 +2632,7 @@ static size_t zend_type_get_num_classes(zend_type type) {
26322632
}
26332633
ZEND_ASSERT(ZEND_TYPE_IS_UNION(type));
26342634
size_t count = 0;
2635-
zend_type *list_type;
2635+
const zend_type *list_type;
26362636

26372637
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
26382638
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
@@ -7048,7 +7048,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
70487048
}
70497049
}
70507050

7051-
static void zend_are_intersection_types_redundant(zend_type left_type, zend_type right_type)
7051+
static void zend_are_intersection_types_redundant(const zend_type left_type, const zend_type right_type)
70527052
{
70537053
ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type));
70547054
ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type));
@@ -7067,9 +7067,9 @@ static void zend_are_intersection_types_redundant(zend_type left_type, zend_type
70677067
}
70687068

70697069
unsigned int sum = 0;
7070-
zend_type *outer_type;
7070+
const zend_type *outer_type;
70717071
ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type)
7072-
zend_type *inner_type;
7072+
const zend_type *inner_type;
70737073
ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type)
70747074
if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) {
70757075
sum++;
@@ -7098,12 +7098,12 @@ static void zend_are_intersection_types_redundant(zend_type left_type, zend_type
70987098
}
70997099
}
71007100

7101-
static void zend_is_intersection_type_redundant_by_single_type(zend_type intersection_type, zend_type single_type)
7101+
static void zend_is_intersection_type_redundant_by_single_type(const zend_type intersection_type, const zend_type single_type)
71027102
{
71037103
ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(intersection_type));
71047104
ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type));
71057105

7106-
zend_type *single_intersection_type = NULL;
7106+
const zend_type *single_intersection_type = NULL;
71077107
ZEND_TYPE_FOREACH(intersection_type, single_intersection_type)
71087108
if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) {
71097109
zend_string *single_type_str = zend_type_to_string(single_type);
@@ -7115,7 +7115,7 @@ static void zend_is_intersection_type_redundant_by_single_type(zend_type interse
71157115
}
71167116

71177117
/* Used by both intersection and union types prior to transforming the type list to a full zend_type */
7118-
static void zend_is_type_list_redundant_by_single_type(zend_type_list *type_list, zend_type type)
7118+
static void zend_is_type_list_redundant_by_single_type(const zend_type_list *type_list, const zend_type type)
71197119
{
71207120
ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(type));
71217121
for (size_t i = 0; i < type_list->num_types - 1; i++) {

0 commit comments

Comments
 (0)