diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-03-18 17:11:56 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-03-18 17:11:56 +0100 |
commit | dcac654fd56a2cecec0c187ba061ecc82bbc9031 (patch) | |
tree | 57fd146f6a4deb209c0ebae32341066cf0cd7836 /Zend | |
parent | 2f73cbb1b10f197674f4adb15f39a1d2d1aa4824 (diff) | |
download | php-git-dcac654fd56a2cecec0c187ba061ecc82bbc9031.tar.gz |
Allow inferring narrowed return type
Even if an explicit return type is given, we might still infer
a more narrow one based on return statements. We shouldn't
pessimize this just because a type has been declared.
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/Optimizer/zend_inference.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 42f37fa0c9..e5d476d01d 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3519,6 +3519,12 @@ static zend_always_inline int _zend_update_type_info( } else { zend_arg_info *ret_info = op_array->arg_info - 1; tmp = zend_fetch_arg_info_type(script, ret_info, &ce); + + // TODO: We could model more precisely how illegal types are converted. + uint32_t extra_types = t1 & ~tmp; + if (!extra_types) { + tmp &= t1; + } } if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) { UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); @@ -4019,6 +4025,11 @@ void zend_func_return_info(const zend_op_array *op_array, return; } + if (!ret->type) { + /* We will intersect the type later. */ + ret->type = MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ARRAY_KEY_ANY; + } + for (j = 0; j < blocks_count; j++) { if ((blocks[j].flags & ZEND_BB_REACHABLE) && blocks[j].len != 0) { zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1; @@ -4178,10 +4189,10 @@ void zend_func_return_info(const zend_op_array *op_array, if (tmp_has_range < 0) { tmp_has_range = 0; } - ret->type = tmp; ret->ce = tmp_ce; ret->is_instanceof = tmp_is_instanceof; } + ret->type &= tmp; ret->range = tmp_range; ret->has_range = tmp_has_range; } |