Skip to content

Commit 2f6e274

Browse files
committed
Convert iterable into an internal alias for Traversable|array
1 parent d4920f4 commit 2f6e274

27 files changed

+59
-120
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,9 +2113,6 @@ static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) {
21132113
if (type_mask & MAY_BE_CALLABLE) {
21142114
result_mask |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
21152115
}
2116-
if (type_mask & MAY_BE_ITERABLE) {
2117-
result_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2118-
}
21192116
if (type_mask & MAY_BE_STATIC) {
21202117
result_mask |= MAY_BE_OBJECT;
21212118
}

Zend/tests/type_declarations/intersection_types/invalid_types/invalid_iterable_type.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ function foo(): iterable&Iterator {}
77

88
?>
99
--EXPECTF--
10-
Fatal error: Type iterable cannot be part of an intersection type in %s on line %d
10+
Fatal error: Type Traversable|array cannot be part of an intersection type in %s on line %d

Zend/tests/type_declarations/intersection_types/variance/invalid5.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ class Test2 extends Test {
1515

1616
?>
1717
--EXPECTF--
18-
Fatal error: Declaration of Test2::method(): X&Y must be compatible with Test::method(): iterable in %s on line %d
18+
Fatal error: Declaration of Test2::method(): X&Y must be compatible with Test::method(): Traversable|array in %s on line %d

Zend/tests/type_declarations/iterable_001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ object(ArrayIterator)#1 (1) {
4545
int(3)
4646
}
4747
}
48-
test(): Argument #1 ($iterable) must be of type iterable, int given, called in %s on line %d
48+
test(): Argument #1 ($iterable) must be of type Traversable|array, int given, called in %s on line %d

Zend/tests/type_declarations/iterable_002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ function baz(iterable $iterable = 1) {
1717

1818
?>
1919
--EXPECTF--
20-
Fatal error: Cannot use int as default value for parameter $iterable of type iterable in %s on line %d
20+
Fatal error: Cannot use int as default value for parameter $iterable of type Traversable|array in %s on line %d

Zend/tests/type_declarations/iterable_003.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ array(0) {
2929
}
3030
object(Generator)#2 (0) {
3131
}
32-
baz(): Return value must be of type iterable, int returned
32+
baz(): Return value must be of type Traversable|array, int returned

Zend/tests/type_declarations/iterable_004.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ class Bar extends Foo {
2121

2222
?>
2323
--EXPECTF--
24-
Fatal error: Declaration of Bar::testScalar(iterable $iterable) must be compatible with Foo::testScalar(int $int) in %s on line %d
24+
Fatal error: Declaration of Bar::testScalar(Traversable|array $iterable) must be compatible with Foo::testScalar(int $int) in %s on line %d

Zend/tests/type_declarations/iterable_005.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ class TestScalar extends Test {
2929

3030
?>
3131
--EXPECTF--
32-
Fatal error: Declaration of TestScalar::method(): int must be compatible with Test::method(): iterable in %s on line %d
32+
Fatal error: Declaration of TestScalar::method(): int must be compatible with Test::method(): Traversable|array in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ function test(): iterable|Traversable {
88

99
?>
1010
--EXPECTF--
11-
Fatal error: Type Traversable|iterable contains both iterable and Traversable, which is redundant in %s on line %d
11+
Fatal error: Duplicate type Traversable is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable_2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ function test(): iterable|Traversable|ArrayAccess {
88

99
?>
1010
--EXPECTF--
11-
Fatal error: Type Traversable|ArrayAccess|iterable contains both iterable and Traversable, which is redundant in %s on line %d
11+
Fatal error: Duplicate type Traversable is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/iterable_and_array.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ function test(): iterable|array {
88

99
?>
1010
--EXPECTF--
11-
Fatal error: Type iterable|array contains both iterable and array, which is redundant in %s on line %d
11+
Fatal error: Duplicate type array is redundant in %s on line %d

Zend/tests/typehints/or_null.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ TypeError: callableF(): Argument #1 ($param) must be of type ?callable, int give
247247
Stack trace:
248248
#0 %s(52): callableF(1)
249249
#1 {main}
250-
TypeError: iterableF(): Argument #1 ($param) must be of type ?iterable, int given, called in %s:%d
250+
TypeError: iterableF(): Argument #1 ($param) must be of type Traversable|array|null, int given, called in %s:%d
251251
Stack trace:
252252
#0 %s(60): iterableF(1)
253253
#1 {main}
@@ -283,7 +283,7 @@ TypeError: returnCallable(): Return value must be of type ?callable, int returne
283283
Stack trace:
284284
#0 %s(138): returnCallable()
285285
#1 {main}
286-
TypeError: returnIterable(): Return value must be of type ?iterable, int returned in %s:%d
286+
TypeError: returnIterable(): Return value must be of type Traversable|array|null, int returned in %s:%d
287287
Stack trace:
288288
#0 %s(148): returnIterable()
289289
#1 {main}
@@ -307,7 +307,7 @@ TypeError: returnMissingCallable(): Return value must be of type ?callable, none
307307
Stack trace:
308308
#0 %s(194): returnMissingCallable()
309309
#1 {main}
310-
TypeError: returnMissingIterable(): Return value must be of type ?iterable, none returned in %s:%d
310+
TypeError: returnMissingIterable(): Return value must be of type Traversable|array|null, none returned in %s:%d
311311
Stack trace:
312312
#0 %s(203): returnMissingIterable()
313313
#1 {main}

Zend/zend_compile.c

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,9 +1225,6 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12251225
if (type_mask & MAY_BE_CALLABLE) {
12261226
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
12271227
}
1228-
if (type_mask & MAY_BE_ITERABLE) {
1229-
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE), /* is_intersection */ false);
1230-
}
12311228
if (type_mask & MAY_BE_OBJECT) {
12321229
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
12331230
}
@@ -1287,7 +1284,7 @@ static void zend_mark_function_as_generator(void) /* {{{ */
12871284

12881285
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
12891286
zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1290-
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
1287+
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
12911288
if (!valid_type) {
12921289
zend_type *single_type;
12931290
ZEND_TYPE_FOREACH(return_type, single_type) {
@@ -6122,6 +6119,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61226119
zend_error_noreturn(E_COMPILE_ERROR,
61236120
"Cannot use \"static\" when no class scope is active");
61246121
}
6122+
61256123
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
61266124
} else {
61276125
zend_string *class_name = zend_ast_get_str(ast);
@@ -6133,6 +6131,17 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61336131
"Type declaration '%s' must be unqualified",
61346132
ZSTR_VAL(zend_string_tolower(class_name)));
61356133
}
6134+
6135+
/* Transform iterable into a type union alias */
6136+
if (type_code == IS_ITERABLE) {
6137+
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6138+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6139+
/* Inform that the type list is a union type */
6140+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
6141+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
6142+
return iterable;
6143+
}
6144+
61366145
return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
61376146
} else {
61386147
const char *correct_name;
@@ -6172,19 +6181,6 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61726181
}
61736182
}
61746183

6175-
static bool zend_type_contains_traversable(zend_type type) {
6176-
zend_type *single_type;
6177-
ZEND_TYPE_FOREACH(type, single_type) {
6178-
if (ZEND_TYPE_HAS_NAME(*single_type)
6179-
&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
6180-
return 1;
6181-
}
6182-
} ZEND_TYPE_FOREACH_END();
6183-
return 0;
6184-
}
6185-
6186-
// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
6187-
// treat it as a built-in type alias.
61886184
static zend_type zend_compile_typename(
61896185
zend_ast *ast, bool force_allow_null) /* {{{ */
61906186
{
@@ -6279,7 +6275,7 @@ static zend_type zend_compile_typename(
62796275
zend_type single_type = zend_compile_single_typename(type_ast);
62806276

62816277
/* An intersection of standard types cannot exist so invalidate it */
6282-
if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
6278+
if (ZEND_TYPE_PURE_MASK(single_type)) {
62836279
zend_string *standard_type_str = zend_type_to_string(single_type);
62846280
zend_error_noreturn(E_COMPILE_ERROR,
62856281
"Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
@@ -6321,18 +6317,6 @@ static zend_type zend_compile_typename(
63216317
}
63226318

63236319
uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
6324-
if ((type_mask & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
6325-
zend_string *type_str = zend_type_to_string(type);
6326-
zend_error_noreturn(E_COMPILE_ERROR,
6327-
"Type %s contains both iterable and array, which is redundant", ZSTR_VAL(type_str));
6328-
}
6329-
6330-
if ((type_mask & MAY_BE_ITERABLE) && zend_type_contains_traversable(type)) {
6331-
zend_string *type_str = zend_type_to_string(type);
6332-
zend_error_noreturn(E_COMPILE_ERROR,
6333-
"Type %s contains both iterable and Traversable, which is redundant",
6334-
ZSTR_VAL(type_str));
6335-
}
63366320

63376321
if (type_mask == MAY_BE_ANY && (orig_ast_attr & ZEND_TYPE_NULLABLE)) {
63386322
zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
@@ -6379,9 +6363,6 @@ static bool zend_is_valid_default_value(zend_type type, zval *value)
63796363
convert_to_double(value);
63806364
return 1;
63816365
}
6382-
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
6383-
return 1;
6384-
}
63856366
return 0;
63866367
}
63876368

Zend/zend_execute.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -909,9 +909,6 @@ static zend_always_inline bool i_zend_check_property_type(zend_property_info *in
909909

910910
uint32_t type_mask = ZEND_TYPE_FULL_MASK(info->type);
911911
ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
912-
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(property)) {
913-
return 1;
914-
}
915912
return zend_verify_scalar_type_hint(type_mask, property, strict, 0);
916913
}
917914

@@ -1048,9 +1045,6 @@ static zend_always_inline bool zend_check_type_slow(
10481045
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
10491046
return 1;
10501047
}
1051-
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(arg)) {
1052-
return 1;
1053-
}
10541048
if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) {
10551049
return 1;
10561050
}
@@ -2846,7 +2840,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
28462840
if (!ZEND_TYPE_IS_SET(type)) {
28472841
return 1;
28482842
}
2849-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
2843+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
28502844
}
28512845

28522846
/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
@@ -3292,9 +3286,6 @@ static zend_always_inline int i_zend_verify_type_assignable_zval(
32923286

32933287
type_mask = ZEND_TYPE_FULL_MASK(type);
32943288
ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
3295-
if (type_mask & MAY_BE_ITERABLE) {
3296-
return zend_is_iterable(zv);
3297-
}
32983289

32993290
/* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
33003291
if (strict) {

Zend/zend_inheritance.c

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -327,21 +327,6 @@ static bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
327327
return 0;
328328
}
329329

330-
static bool zend_type_contains_traversable(zend_type type) {
331-
zend_type *single_type;
332-
if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) {
333-
return 1;
334-
}
335-
336-
ZEND_TYPE_FOREACH(type, single_type) {
337-
if (ZEND_TYPE_HAS_NAME(*single_type)
338-
&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
339-
return 1;
340-
}
341-
} ZEND_TYPE_FOREACH_END();
342-
return 0;
343-
}
344-
345330
static bool zend_type_permits_self(
346331
zend_type type, zend_class_entry *scope, zend_class_entry *self) {
347332
if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) {
@@ -472,15 +457,6 @@ static inheritance_status zend_is_class_subtype_of_type(
472457
return INHERITANCE_SUCCESS;
473458
}
474459
}
475-
if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_ITERABLE) {
476-
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name);
477-
if (!fe_ce) {
478-
have_unresolved = 1;
479-
} else if (unlinked_instanceof(fe_ce, zend_ce_traversable)) {
480-
track_class_dependency(fe_ce, fe_class_name);
481-
return INHERITANCE_SUCCESS;
482-
}
483-
}
484460

485461
zend_type *single_type;
486462

@@ -566,18 +542,6 @@ static inheritance_status zend_perform_covariant_type_check(
566542
uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type);
567543
uint32_t added_types = fe_type_mask & ~proto_type_mask;
568544
if (added_types) {
569-
// TODO: Make "iterable" an alias of "array|Traversable" instead,
570-
// so these special cases will be handled automatically.
571-
if ((added_types & MAY_BE_ITERABLE)
572-
&& (proto_type_mask & MAY_BE_ARRAY)
573-
&& zend_type_contains_traversable(proto_type)) {
574-
/* Replacing array|Traversable with iterable is okay */
575-
added_types &= ~MAY_BE_ITERABLE;
576-
}
577-
if ((added_types & MAY_BE_ARRAY) && (proto_type_mask & MAY_BE_ITERABLE)) {
578-
/* Replacing iterable with array is okay */
579-
added_types &= ~MAY_BE_ARRAY;
580-
}
581545
if ((added_types & MAY_BE_STATIC)
582546
&& zend_type_permits_self(proto_type, proto_scope, fe_scope)) {
583547
/* Replacing type that accepts self with static is okay */
@@ -604,19 +568,16 @@ static inheritance_status zend_perform_covariant_type_check(
604568
* We still perform a class lookup for forward-compatibility reasons,
605569
* as we may have named types in the future that are not classes
606570
* (such as typedefs). */
607-
if (proto_type_mask & (MAY_BE_OBJECT|MAY_BE_ITERABLE)) {
608-
bool any_class = (proto_type_mask & MAY_BE_OBJECT) != 0;
571+
if (proto_type_mask & MAY_BE_OBJECT) {
609572
ZEND_TYPE_FOREACH(fe_type, single_type) {
610573
zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type);
611574
if (!fe_class_name) {
612575
continue;
613576
}
614577
zend_class_entry *fe_ce = lookup_class(fe_scope, fe_class_name);
615578
if (fe_ce) {
616-
if (any_class || unlinked_instanceof(fe_ce, zend_ce_traversable)) {
617-
track_class_dependency(fe_ce, fe_class_name);
618-
return INHERITANCE_SUCCESS;
619-
}
579+
track_class_dependency(fe_ce, fe_class_name);
580+
return INHERITANCE_SUCCESS;
620581
} else {
621582
have_unresolved = true;
622583
}

Zend/zend_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
562562
_(ZEND_STR_FALSE, "false") \
563563
_(ZEND_STR_NULL_LOWERCASE, "null") \
564564
_(ZEND_STR_MIXED, "mixed") \
565+
_(ZEND_STR_TRAVERSABLE, "Traversable") \
565566
_(ZEND_STR_SLEEP, "__sleep") \
566567
_(ZEND_STR_WAKEUP, "__wakeup") \
567568
_(ZEND_STR_CASES, "cases") \

Zend/zend_type_info.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
/* These are used in zend_type, but not for type inference.
3939
* They are allowed to overlap with types used during inference. */
4040
#define MAY_BE_CALLABLE (1 << IS_CALLABLE)
41-
#define MAY_BE_ITERABLE (1 << IS_ITERABLE)
4241
#define MAY_BE_VOID (1 << IS_VOID)
4342
#define MAY_BE_NEVER (1 << IS_NEVER)
4443
#define MAY_BE_STATIC (1 << IS_STATIC)

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12320,7 +12320,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1232012320
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1232112321

1232212322
if (flags == ZEND_FETCH_DIM_WRITE) {
12323-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
12323+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1232412324
if (!type_loaded) {
1232512325
type_loaded = 1;
1232612326
| MEM_ACCESS_32_WITH_UOFFSET ldr, REG2w, FCARG1x, (prop_info->offset + offsetof(zval,u1.type_info)), TMP1

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
17411741
if (!ZEND_TYPE_IS_SET(type)) {
17421742
return 1;
17431743
}
1744-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
1744+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
17451745
}
17461746

17471747
static zend_property_info *zend_object_fetch_property_type_info(
@@ -1886,7 +1886,7 @@ static void ZEND_FASTCALL zend_jit_check_array_promotion(zval *val, zend_propert
18861886
if ((Z_TYPE_P(val) <= IS_FALSE
18871887
|| (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE))
18881888
&& ZEND_TYPE_IS_SET(prop->type)
1889-
&& (ZEND_TYPE_FULL_MASK(prop->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
1889+
&& (ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_ARRAY) == 0) {
18901890
zend_string *type_str = zend_type_to_string(prop->type);
18911891
zend_type_error(
18921892
"Cannot auto-initialize an array inside property %s::$%s of type %s",

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13043,7 +13043,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1304313043
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1304413044

1304513045
if (flags == ZEND_FETCH_DIM_WRITE) {
13046-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
13046+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1304713047
if (!type_loaded) {
1304813048
type_loaded = 1;
1304913049
| mov edx, dword [FCARG1a + prop_info->offset + 8]

ext/opcache/tests/iterable_type_optimization.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ test(new stdClass);
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: Uncaught TypeError: test(): Return value must be of type iterable, stdClass returned in %s:%d
15+
Fatal error: Uncaught TypeError: test(): Return value must be of type Traversable|array, stdClass returned in %s:%d
1616
Stack trace:
1717
#0 %s(%d): test(Object(stdClass))
1818
#1 {main}

ext/reflection/php_reflection.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,9 +3079,6 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30793079
if (type_mask & MAY_BE_CALLABLE) {
30803080
append_type_mask(return_value, MAY_BE_CALLABLE);
30813081
}
3082-
if (type_mask & MAY_BE_ITERABLE) {
3083-
append_type_mask(return_value, MAY_BE_ITERABLE);
3084-
}
30853082
if (type_mask & MAY_BE_OBJECT) {
30863083
append_type_mask(return_value, MAY_BE_OBJECT);
30873084
}

ext/reflection/tests/ReflectionClass_isArray.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
2121
bool(true)
2222

2323
Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
24-
bool(false)
24+
bool(true)
2525

2626
Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
2727
bool(false)

0 commit comments

Comments
 (0)