diff options
author | Aaron Piotrowski <aaron@trowski.com> | 2016-06-04 09:44:49 -0500 |
---|---|---|
committer | Aaron Piotrowski <aaron@trowski.com> | 2016-06-04 09:44:49 -0500 |
commit | 4da3e77b4ce4beb1735a679c58cb2bce3fdfece1 (patch) | |
tree | 1cfc63254e939f231fcba9587f453e64dd0c73fe /Zend/zend_inheritance.c | |
parent | bea9df52811d1b5f99fd59dfd4d8232d8448b538 (diff) | |
download | php-git-4da3e77b4ce4beb1735a679c58cb2bce3fdfece1.tar.gz |
Covariance on inheriting classes with iterable
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r-- | Zend/zend_inheritance.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 44abfb6ffb..dd1442e828 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -22,6 +22,7 @@ #include "zend_compile.h" #include "zend_execute.h" #include "zend_inheritance.h" +#include "zend_interfaces.h" #include "zend_smart_str.h" #include "zend_inheritance.h" @@ -167,6 +168,26 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */ } /* }}} */ +static zend_bool zend_iterable_type_check(zend_arg_info *arg_info) /* {{{ */ +{ + if (arg_info->class_name) { + zend_class_entry *ce; + + ce = zend_lookup_class(arg_info->class_name); + + if (ce && instanceof_function(ce, zend_ce_traversable)) { + return 1; + } + } + + if (arg_info->type_hint == IS_ITERABLE || arg_info->type_hint == IS_ARRAY) { + return 1; + } + + return 0; +} +/* }}} */ + static 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) /* {{{ */ { 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 } else { proto_arg_info = &proto->common.arg_info[proto->common.num_args]; } + + if (fe_arg_info->type_hint == IS_ITERABLE && zend_iterable_type_check(proto_arg_info)) { + continue; + } if (!zend_do_perform_type_hint_check(fe, fe_arg_info, proto, proto_arg_info)) { return 0; @@ -338,6 +363,10 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c if (!(fe->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { return 0; } + + if (proto->common.arg_info[-1].type_hint == IS_ITERABLE && zend_iterable_type_check(fe->common.arg_info - 1)) { + return 1; + } if (!zend_do_perform_type_hint_check(fe, fe->common.arg_info - 1, proto, proto->common.arg_info - 1)) { return 0; |