diff --git a/src/Parser/BinaryOpTrait.php b/src/Parser/BinaryOpTrait.php index 8d4d32b1..83332cb4 100644 --- a/src/Parser/BinaryOpTrait.php +++ b/src/Parser/BinaryOpTrait.php @@ -264,17 +264,17 @@ trait BinaryOpTrait $this->flattenConcatExpr($expr, $items); $argList = $prefixExpressions; - foreach ($items as $index => $item) { - // 在字符串拼接中,除了第一个元素之外,剩下的字符串如果出现空字符串,忽略这个字符串 - if ($index > 0 && $item->value == '') { + foreach ($items as $item) { + // Keep one operand so concat still performs PHP string coercion. + // Prefix expressions are operands too (for example, the left-hand + // value of `.=`), so an empty RHS literal can be omitted there. + if ($argList !== [] && $this->isScalarString($item) && $item->value === '') { continue; } - $argList[] = $this->prepareConcatOperand($this->parseExprAsValue($item), $this->detectTypeOfExpr($item)); - } - - if (sizeof($argList) == 1) { - return $argList[0]; + $type = $this->detectTypeOfExpr($item); + $parsed = $this->parseExprAsValue($item); + $argList[] = $this->prepareConcatOperand($parsed, $type); } return Symbol::concat() . '({' . implode(', ', $argList) . '})'; diff --git a/tests/compiler/concat_empty.phpt b/tests/compiler/concat_empty.phpt index d759d8e1..a0aeebf1 100644 --- a/tests/compiler/concat_empty.phpt +++ b/tests/compiler/concat_empty.phpt @@ -5,8 +5,29 @@ Concat empty strings function main() { var_dump('' . 1 . '' . 'a' . ''); var_dump('' . 1); + var_dump(1 . ''); + var_dump(false . ''); + var_dump('' . '' . ''); + + $value = 'value'; + var_dump('' . $value . ''); + var_dump('' . get_value() . ''); + + $number = 1; + $number .= ''; + var_dump($number); +} + +function get_value(): string { + return 'called'; } ?> --EXPECT-- string(2) "1a" string(1) "1" +string(1) "1" +string(0) "" +string(0) "" +string(5) "value" +string(6) "called" +string(1) "1"