2222#include "zend_compile.h"
2323#include "zend_execute.h"
2424#include "zend_inheritance.h"
25+ #include "zend_interfaces.h"
2526#include "zend_smart_str.h"
2627#include "zend_inheritance.h"
2728
@@ -167,6 +168,26 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
167168}
168169/* }}} */
169170
171+ static zend_bool zend_iterable_type_check (zend_arg_info * arg_info ) /* {{{ */
172+ {
173+ if (arg_info -> class_name ) {
174+ zend_class_entry * ce ;
175+
176+ ce = zend_lookup_class (arg_info -> class_name );
177+
178+ if (ce && instanceof_function (ce , zend_ce_traversable )) {
179+ return 1 ;
180+ }
181+ }
182+
183+ if (arg_info -> type_hint == IS_ITERABLE || arg_info -> type_hint == IS_ARRAY ) {
184+ return 1 ;
185+ }
186+
187+ return 0 ;
188+ }
189+ /* }}} */
190+
170191static int zend_do_perform_type_hint_check (const zend_function * fe , zend_arg_info * fe_arg_info , const zend_function * proto , zend_arg_info * proto_arg_info ) /* {{{ */
171192{
172193 if (ZEND_LOG_XOR (fe_arg_info -> class_name , proto_arg_info -> class_name )) {
@@ -314,6 +335,10 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
314335 } else {
315336 proto_arg_info = & proto -> common .arg_info [proto -> common .num_args ];
316337 }
338+
339+ if (fe_arg_info -> type_hint == IS_ITERABLE && zend_iterable_type_check (proto_arg_info )) {
340+ continue ;
341+ }
317342
318343 if (!zend_do_perform_type_hint_check (fe , fe_arg_info , proto , proto_arg_info )) {
319344 return 0 ;
@@ -338,6 +363,10 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
338363 if (!(fe -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE )) {
339364 return 0 ;
340365 }
366+
367+ if (proto -> common .arg_info [-1 ].type_hint == IS_ITERABLE && zend_iterable_type_check (fe -> common .arg_info - 1 )) {
368+ return 1 ;
369+ }
341370
342371 if (!zend_do_perform_type_hint_check (fe , fe -> common .arg_info - 1 , proto , proto -> common .arg_info - 1 )) {
343372 return 0 ;
0 commit comments