From e019f21550678dd5f5fb91d85cd572fece44b111 Mon Sep 17 00:00:00 2001 From: Alessio Giacobbe Date: Fri, 28 Aug 2026 17:56:23 +0200 Subject: [PATCH] fix(optimizer): keep argument side effects when folding is_int/is_float/is_bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doFoldSsaType folded a statically type-known is_int()/is_float()/ is_bool() call to the literal `true`, discarding the argument entirely. With `function f(): int`, `if (is_int(f()))` compiled to `if (true)` and f() was never invoked — its side effects silently vanished. Fold to a bare `true` only for plain variables and scalar literals; for any other argument emit `((void)(expr), true)` so the operand is still evaluated, mirroring how genIsNull already handles native scalar operands. --- src/Optimizer/FuncCallOptimizer.php | 11 ++++- .../is-type-fold-side-effects.phpt | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/compiler/optimizations/is-type-fold-side-effects.phpt diff --git a/src/Optimizer/FuncCallOptimizer.php b/src/Optimizer/FuncCallOptimizer.php index fe2ae690..7f76a33b 100644 --- a/src/Optimizer/FuncCallOptimizer.php +++ b/src/Optimizer/FuncCallOptimizer.php @@ -681,7 +681,16 @@ trait FuncCallOptimizer if (count($expr->args) !== 1 || !($expr->args[0] instanceof Node\Arg)) { return false; } - return ($this->detectTypeOfExpr($expr->args[0]->value) === $expectType) ? 'true' : false; + $value = $expr->args[0]->value; + if ($this->detectTypeOfExpr($value) !== $expectType) { + return false; + } + if ($value instanceof Node\Expr\Variable || $value instanceof Node\Scalar) { + return 'true'; + } + // The argument can carry side effects (a call, an increment). Keep + // evaluating it, as genIsNull does for native scalar operands. + return '((void) (' . $this->parseExprAsValue($value) . '), true)'; } // ========================================================================= diff --git a/tests/compiler/optimizations/is-type-fold-side-effects.phpt b/tests/compiler/optimizations/is-type-fold-side-effects.phpt new file mode 100644 index 00000000..9c57b948 --- /dev/null +++ b/tests/compiler/optimizations/is-type-fold-side-effects.phpt @@ -0,0 +1,44 @@ +--TEST-- +Folded is_int/is_float/is_bool must keep evaluating side-effect arguments +--FILE-- + +--EXPECT-- +int-called +is-int +float-called +is-float +bool-called +is-bool +var-int