Skip to content

Commit 176b604

Browse files
committed
Convert iterable into an internal alias for Traversable|array
1 parent fb52b3c commit 176b604

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
@@ -2199,9 +2199,6 @@ static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) {
21992199
if (type_mask & MAY_BE_CALLABLE) {
22002200
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;
22012201
}
2202-
if (type_mask & MAY_BE_ITERABLE) {
2203-
result_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2204-
}
22052202
if (type_mask & MAY_BE_STATIC) {
22062203
result_mask |= MAY_BE_OBJECT;
22072204
}

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
@@ -1264,9 +1264,6 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12641264
if (type_mask & MAY_BE_CALLABLE) {
12651265
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
12661266
}
1267-
if (type_mask & MAY_BE_ITERABLE) {
1268-
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE), /* is_intersection */ false);
1269-
}
12701267
if (type_mask & MAY_BE_OBJECT) {
12711268
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
12721269
}
@@ -1326,7 +1323,7 @@ static void zend_mark_function_as_generator(void) /* {{{ */
13261323

13271324
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
13281325
zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1329-
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
1326+
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
13301327
if (!valid_type) {
13311328
zend_type *single_type;
13321329
ZEND_TYPE_FOREACH(return_type, single_type) {
@@ -6192,6 +6189,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61926189
zend_error_noreturn(E_COMPILE_ERROR,
61936190
"Cannot use \"static\" when no class scope is active");
61946191
}
6192+
61956193
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
61966194
} else {
61976195
zend_string *class_name = zend_ast_get_str(ast);
@@ -6203,6 +6201,17 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
62036201
"Type declaration '%s' must be unqualified",
62046202
ZSTR_VAL(zend_string_tolower(class_name)));
62056203
}
6204+
6205+
/* Transform iterable into a type union alias */
6206+
if (type_code == IS_ITERABLE) {
6207+
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6208+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6209+
/* Inform that the type list is a union type */
6210+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
6211+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
6212+
return iterable;
6213+
}
6214+
62066215
return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
62076216
} else {
62086217
const char *correct_name;
@@ -6240,19 +6249,6 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
62406249
}
62416250
}
62426251

6243-
static bool zend_type_contains_traversable(zend_type type) {
6244-
zend_type *single_type;
6245-
ZEND_TYPE_FOREACH(type, single_type) {
6246-
if (ZEND_TYPE_HAS_NAME(*single_type)
6247-
&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
6248-
return 1;
6249-
}
6250-
} ZEND_TYPE_FOREACH_END();
6251-
return 0;
6252-
}
6253-
6254-
// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
6255-
// treat it as a built-in type alias.
62566252
static zend_type zend_compile_typename(
62576253
zend_ast *ast, bool force_allow_null) /* {{{ */
62586254
{
@@ -6347,7 +6343,7 @@ static zend_type zend_compile_typename(
63476343
zend_type single_type = zend_compile_single_typename(type_ast);
63486344

63496345
/* An intersection of standard types cannot exist so invalidate it */
6350-
if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
6346+
if (ZEND_TYPE_PURE_MASK(single_type)) {
63516347
zend_string *standard_type_str = zend_type_to_string(single_type);
63526348
zend_error_noreturn(E_COMPILE_ERROR,
63536349
"Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
@@ -6389,18 +6385,6 @@ static zend_type zend_compile_typename(
63896385
}
63906386

63916387
uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
6392-
if ((type_mask & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
6393-
zend_string *type_str = zend_type_to_string(type);
6394-
zend_error_noreturn(E_COMPILE_ERROR,
6395-
"Type %s contains both iterable and array, which is redundant", ZSTR_VAL(type_str));
6396-
}
6397-
6398-
if ((type_mask & MAY_BE_ITERABLE) && zend_type_contains_traversable(type)) {
6399-
zend_string *type_str = zend_type_to_string(type);
6400-
zend_error_noreturn(E_COMPILE_ERROR,
6401-
"Type %s contains both iterable and Traversable, which is redundant",
6402-
ZSTR_VAL(type_str));
6403-
}
64046388

64056389
if (type_mask == MAY_BE_ANY && (orig_ast_attr & ZEND_TYPE_NULLABLE)) {
64066390
zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
@@ -6447,9 +6431,6 @@ static bool zend_is_valid_default_value(zend_type type, zval *value)
64476431
convert_to_double(value);
64486432
return 1;
64496433
}
6450-
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
6451-
return 1;
6452-
}
64536434
return 0;
64546435
}
64556436

Zend/zend_execute.c

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

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

@@ -1049,9 +1046,6 @@ static zend_always_inline bool zend_check_type_slow(
10491046
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
10501047
return 1;
10511048
}
1052-
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(arg)) {
1053-
return 1;
1054-
}
10551049
if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) {
10561050
return 1;
10571051
}
@@ -2784,7 +2778,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
27842778
if (!ZEND_TYPE_IS_SET(type)) {
27852779
return 1;
27862780
}
2787-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
2781+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
27882782
}
27892783

27902784
/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
@@ -3230,9 +3224,6 @@ static zend_always_inline int i_zend_verify_type_assignable_zval(
32303224

32313225
type_mask = ZEND_TYPE_FULL_MASK(type);
32323226
ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
3233-
if (type_mask & MAY_BE_ITERABLE) {
3234-
return zend_is_iterable(zv);
3235-
}
32363227

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

Zend/zend_inheritance.c

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

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

486462
zend_type *single_type;
487463

@@ -576,18 +552,6 @@ static inheritance_status zend_perform_covariant_type_check(
576552
uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type);
577553
uint32_t added_types = fe_type_mask & ~proto_type_mask;
578554
if (added_types) {
579-
// TODO: Make "iterable" an alias of "array|Traversable" instead,
580-
// so these special cases will be handled automatically.
581-
if ((added_types & MAY_BE_ITERABLE)
582-
&& (proto_type_mask & MAY_BE_ARRAY)
583-
&& zend_type_contains_traversable(proto_type)) {
584-
/* Replacing array|Traversable with iterable is okay */
585-
added_types &= ~MAY_BE_ITERABLE;
586-
}
587-
if ((added_types & MAY_BE_ARRAY) && (proto_type_mask & MAY_BE_ITERABLE)) {
588-
/* Replacing iterable with array is okay */
589-
added_types &= ~MAY_BE_ARRAY;
590-
}
591555
if ((added_types & MAY_BE_STATIC)
592556
&& zend_type_permits_self(proto_type, proto_scope, fe_scope)) {
593557
/* Replacing type that accepts self with static is okay */
@@ -614,8 +578,7 @@ static inheritance_status zend_perform_covariant_type_check(
614578
* We still perform a class lookup for forward-compatibility reasons,
615579
* as we may have named types in the future that are not classes
616580
* (such as typedefs). */
617-
if (proto_type_mask & (MAY_BE_OBJECT|MAY_BE_ITERABLE)) {
618-
bool any_class = (proto_type_mask & MAY_BE_OBJECT) != 0;
581+
if (proto_type_mask & MAY_BE_OBJECT) {
619582
ZEND_TYPE_FOREACH(fe_type, single_type) {
620583
zend_class_entry *fe_ce;
621584
zend_string *fe_class_name = get_class_from_type(&fe_ce, fe_scope, *single_type);
@@ -626,10 +589,8 @@ static inheritance_status zend_perform_covariant_type_check(
626589
fe_ce = lookup_class(fe_scope, fe_class_name);
627590
}
628591
if (fe_ce) {
629-
if (any_class || unlinked_instanceof(fe_ce, zend_ce_traversable)) {
630-
track_class_dependency(fe_ce, fe_class_name);
631-
return INHERITANCE_SUCCESS;
632-
}
592+
track_class_dependency(fe_ce, fe_class_name);
593+
return INHERITANCE_SUCCESS;
633594
} else {
634595
have_unresolved = true;
635596
}

Zend/zend_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
555555
_(ZEND_STR_FALSE, "false") \
556556
_(ZEND_STR_NULL_LOWERCASE, "null") \
557557
_(ZEND_STR_MIXED, "mixed") \
558+
_(ZEND_STR_TRAVERSABLE, "Traversable") \
558559
_(ZEND_STR_SLEEP, "__sleep") \
559560
_(ZEND_STR_WAKEUP, "__wakeup") \
560561
_(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
@@ -11906,7 +11906,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1190611906
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1190711907

1190811908
if (flags == ZEND_FETCH_DIM_WRITE) {
11909-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
11909+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1191011910
| cmp REG2w, #IS_FALSE
1191111911
| ble >1
1191211912
|.cold_code

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
15021502
if (!ZEND_TYPE_IS_SET(type)) {
15031503
return 1;
15041504
}
1505-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
1505+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
15061506
}
15071507

15081508
static zend_property_info *zend_object_fetch_property_type_info(
@@ -1647,7 +1647,7 @@ static void ZEND_FASTCALL zend_jit_check_array_promotion(zval *val, zend_propert
16471647
if ((Z_TYPE_P(val) <= IS_FALSE
16481648
|| (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE))
16491649
&& ZEND_TYPE_IS_SET(prop->type)
1650-
&& (ZEND_TYPE_FULL_MASK(prop->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
1650+
&& (ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_ARRAY) == 0) {
16511651
zend_string *type_str = zend_type_to_string(prop->type);
16521652
zend_type_error(
16531653
"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
@@ -12595,7 +12595,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1259512595
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1259612596

1259712597
if (flags == ZEND_FETCH_DIM_WRITE) {
12598-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
12598+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1259912599
| cmp dl, IS_FALSE
1260012600
| jle >1
1260112601
|.cold_code

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
@@ -3094,9 +3094,6 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30943094
if (type_mask & MAY_BE_CALLABLE) {
30953095
append_type_mask(return_value, MAY_BE_CALLABLE);
30963096
}
3097-
if (type_mask & MAY_BE_ITERABLE) {
3098-
append_type_mask(return_value, MAY_BE_ITERABLE);
3099-
}
31003097
if (type_mask & MAY_BE_OBJECT) {
31013098
append_type_mask(return_value, MAY_BE_OBJECT);
31023099
}

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)