Skip to content

Commit ceaa33c

Browse files
committed
Handle intersection in can_elide_return_type_check()
1 parent e732440 commit ceaa33c

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,17 +312,21 @@ static inline bool can_elide_return_type_check(
312312

313313
if (disallowed_types == MAY_BE_OBJECT && use_info->ce && ZEND_TYPE_IS_COMPLEX(arg_info->type)) {
314314
zend_type *single_type;
315+
/* For intersection: result==false is failure, default is success.
316+
* For union: result==true is success, default is failure. */
317+
bool is_intersection = ZEND_TYPE_IS_INTERSECTION(arg_info->type);
315318
ZEND_TYPE_FOREACH(arg_info->type, single_type) {
316319
if (ZEND_TYPE_HAS_NAME(*single_type)) {
317320
zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type));
318321
zend_class_entry *ce = zend_optimizer_get_class_entry(script, lcname);
319322
zend_string_release(lcname);
320-
if (ce && ZEND_TYPE_IS_UNION(arg_info->type) && safe_instanceof(use_info->ce, ce)) {
321-
/* One of the class union types matched. */
322-
return true;
323+
bool result = ce && safe_instanceof(use_info->ce, ce);
324+
if (result == !is_intersection) {
325+
return result;
323326
}
324327
}
325328
} ZEND_TYPE_FOREACH_END();
329+
return is_intersection;
326330
}
327331

328332
return false;

ext/opcache/tests/opt/verify_return_type.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ function getClassUnion(): stdClass|FooBar {
5151
return new stdClass;
5252
}
5353

54+
function getClassIntersection(): Traversable&Countable {
55+
return new ArrayObject;
56+
}
57+
5458
?>
5559
--EXPECTF--
5660
$_main:
@@ -69,6 +73,16 @@ getClassUnion:
6973
LIVE RANGES:
7074
0: 0001 - 0002 (new)
7175

76+
getClassIntersection:
77+
; (lines=3, args=0, vars=0, tmps=1)
78+
; (after optimizer)
79+
; %s
80+
0000 V0 = NEW 0 string("ArrayObject")
81+
0001 DO_FCALL
82+
0002 RETURN V0
83+
LIVE RANGES:
84+
0: 0001 - 0002 (new)
85+
7286
Test1::getIntOrFloat:
7387
; (lines=2, args=1, vars=1, tmps=0)
7488
; (after optimizer)

0 commit comments

Comments
 (0)