Skip to content

Commit e6d4f10

Browse files
committed
Convert iterable into an internal alias for Traversable|array
1 parent ac08808 commit e6d4f10

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
@@ -2269,9 +2269,6 @@ static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) {
22692269
if (type_mask & MAY_BE_CALLABLE) {
22702270
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;
22712271
}
2272-
if (type_mask & MAY_BE_ITERABLE) {
2273-
result_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2274-
}
22752272
if (type_mask & MAY_BE_STATIC) {
22762273
result_mask |= MAY_BE_OBJECT;
22772274
}

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
@@ -1237,9 +1237,6 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12371237
if (type_mask & MAY_BE_CALLABLE) {
12381238
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
12391239
}
1240-
if (type_mask & MAY_BE_ITERABLE) {
1241-
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE), /* is_intersection */ false);
1242-
}
12431240
if (type_mask & MAY_BE_OBJECT) {
12441241
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
12451242
}
@@ -1299,7 +1296,7 @@ static void zend_mark_function_as_generator(void) /* {{{ */
12991296

13001297
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
13011298
zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1302-
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
1299+
bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
13031300
if (!valid_type) {
13041301
zend_type *single_type;
13051302
ZEND_TYPE_FOREACH(return_type, single_type) {
@@ -6162,6 +6159,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61626159
zend_error_noreturn(E_COMPILE_ERROR,
61636160
"Cannot use \"static\" when no class scope is active");
61646161
}
6162+
61656163
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
61666164
} else {
61676165
zend_string *class_name = zend_ast_get_str(ast);
@@ -6173,6 +6171,17 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61736171
"Type declaration '%s' must be unqualified",
61746172
ZSTR_VAL(zend_string_tolower(class_name)));
61756173
}
6174+
6175+
/* Transform iterable into a type union alias */
6176+
if (type_code == IS_ITERABLE) {
6177+
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6178+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6179+
/* Inform that the type list is a union type */
6180+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
6181+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
6182+
return iterable;
6183+
}
6184+
61766185
return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
61776186
} else {
61786187
const char *correct_name;
@@ -6212,19 +6221,6 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
62126221
}
62136222
}
62146223

6215-
static bool zend_type_contains_traversable(zend_type type) {
6216-
zend_type *single_type;
6217-
ZEND_TYPE_FOREACH(type, single_type) {
6218-
if (ZEND_TYPE_HAS_NAME(*single_type)
6219-
&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
6220-
return 1;
6221-
}
6222-
} ZEND_TYPE_FOREACH_END();
6223-
return 0;
6224-
}
6225-
6226-
// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
6227-
// treat it as a built-in type alias.
62286224
static zend_type zend_compile_typename(
62296225
zend_ast *ast, bool force_allow_null) /* {{{ */
62306226
{
@@ -6319,7 +6315,7 @@ static zend_type zend_compile_typename(
63196315
zend_type single_type = zend_compile_single_typename(type_ast);
63206316

63216317
/* An intersection of standard types cannot exist so invalidate it */
6322-
if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
6318+
if (ZEND_TYPE_PURE_MASK(single_type)) {
63236319
zend_string *standard_type_str = zend_type_to_string(single_type);
63246320
zend_error_noreturn(E_COMPILE_ERROR,
63256321
"Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
@@ -6361,18 +6357,6 @@ static zend_type zend_compile_typename(
63616357
}
63626358

63636359
uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
6364-
if ((type_mask & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
6365-
zend_string *type_str = zend_type_to_string(type);
6366-
zend_error_noreturn(E_COMPILE_ERROR,
6367-
"Type %s contains both iterable and array, which is redundant", ZSTR_VAL(type_str));
6368-
}
6369-
6370-
if ((type_mask & MAY_BE_ITERABLE) && zend_type_contains_traversable(type)) {
6371-
zend_string *type_str = zend_type_to_string(type);
6372-
zend_error_noreturn(E_COMPILE_ERROR,
6373-
"Type %s contains both iterable and Traversable, which is redundant",
6374-
ZSTR_VAL(type_str));
6375-
}
63766360

63776361
if (type_mask == MAY_BE_ANY && (orig_ast_attr & ZEND_TYPE_NULLABLE)) {
63786362
zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
@@ -6419,9 +6403,6 @@ static bool zend_is_valid_default_value(zend_type type, zval *value)
64196403
convert_to_double(value);
64206404
return 1;
64216405
}
6422-
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
6423-
return 1;
6424-
}
64256406
return 0;
64266407
}
64276408

Zend/zend_execute.c

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

913913
uint32_t type_mask = ZEND_TYPE_FULL_MASK(info->type);
914914
ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
915-
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(property)) {
916-
return 1;
917-
}
918915
return zend_verify_scalar_type_hint(type_mask, property, strict, 0);
919916
}
920917

@@ -1051,9 +1048,6 @@ static zend_always_inline bool zend_check_type_slow(
10511048
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
10521049
return 1;
10531050
}
1054-
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(arg)) {
1055-
return 1;
1056-
}
10571051
if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) {
10581052
return 1;
10591053
}
@@ -2779,7 +2773,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
27792773
if (!ZEND_TYPE_IS_SET(type)) {
27802774
return 1;
27812775
}
2782-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
2776+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
27832777
}
27842778

27852779
/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
@@ -3225,9 +3219,6 @@ static zend_always_inline int i_zend_verify_type_assignable_zval(
32253219

32263220
type_mask = ZEND_TYPE_FULL_MASK(type);
32273221
ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
3228-
if (type_mask & MAY_BE_ITERABLE) {
3229-
return zend_is_iterable(zv);
3230-
}
32313222

32323223
/* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
32333224
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
@@ -561,6 +561,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
561561
_(ZEND_STR_FALSE, "false") \
562562
_(ZEND_STR_NULL_LOWERCASE, "null") \
563563
_(ZEND_STR_MIXED, "mixed") \
564+
_(ZEND_STR_TRAVERSABLE, "Traversable") \
564565
_(ZEND_STR_SLEEP, "__sleep") \
565566
_(ZEND_STR_WAKEUP, "__wakeup") \
566567
_(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
@@ -11958,7 +11958,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1195811958
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1195911959

1196011960
if (flags == ZEND_FETCH_DIM_WRITE) {
11961-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
11961+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1196211962
| cmp REG2w, #IS_FALSE
1196311963
| ble >1
1196411964
|.cold_code

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ static zend_always_inline bool check_type_array_assignable(zend_type type) {
15451545
if (!ZEND_TYPE_IS_SET(type)) {
15461546
return 1;
15471547
}
1548-
return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
1548+
return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
15491549
}
15501550

15511551
static zend_property_info *zend_object_fetch_property_type_info(
@@ -1690,7 +1690,7 @@ static void ZEND_FASTCALL zend_jit_check_array_promotion(zval *val, zend_propert
16901690
if ((Z_TYPE_P(val) <= IS_FALSE
16911691
|| (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE))
16921692
&& ZEND_TYPE_IS_SET(prop->type)
1693-
&& (ZEND_TYPE_FULL_MASK(prop->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
1693+
&& (ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_ARRAY) == 0) {
16941694
zend_string *type_str = zend_type_to_string(prop->type);
16951695
zend_type_error(
16961696
"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
@@ -12644,7 +12644,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1264412644
uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
1264512645

1264612646
if (flags == ZEND_FETCH_DIM_WRITE) {
12647-
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) == 0) {
12647+
if ((ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_ARRAY) == 0) {
1264812648
| cmp dl, IS_FALSE
1264912649
| jle >1
1265012650
|.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
@@ -3073,9 +3073,6 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30733073
if (type_mask & MAY_BE_CALLABLE) {
30743074
append_type_mask(return_value, MAY_BE_CALLABLE);
30753075
}
3076-
if (type_mask & MAY_BE_ITERABLE) {
3077-
append_type_mask(return_value, MAY_BE_ITERABLE);
3078-
}
30793076
if (type_mask & MAY_BE_OBJECT) {
30803077
append_type_mask(return_value, MAY_BE_OBJECT);
30813078
}

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)