From 0da07cb06505af8dd665ecdbe18975417220c2ef Mon Sep 17 00:00:00 2001 From: Yurun Date: Wed, 15 Jul 2026 19:06:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(compiler):=20=E4=BF=AE=E5=A4=8D=E5=AF=B9?= =?UTF-8?q?=E6=9C=AA=E5=AE=9A=E4=B9=89=E5=8F=98=E9=87=8F=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20=3F=3F=3D=20=E6=97=B6=E7=9A=84=E7=BC=96=E8=AF=91=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Parser/AssignOpTrait.php | 14 +++++++++++--- .../coalesce/assign-coalesce-undefined-var.phpt | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/compiler/coalesce/assign-coalesce-undefined-var.phpt diff --git a/src/Parser/AssignOpTrait.php b/src/Parser/AssignOpTrait.php index cf826761..826cd011 100644 --- a/src/Parser/AssignOpTrait.php +++ b/src/Parser/AssignOpTrait.php @@ -862,6 +862,17 @@ trait AssignOpTrait protected function parseAssignOpCoalesce(Expr\AssignOp\Coalesce $expr): string { $this->checkLeftValue($expr->var); + + // PHP 允许对未定义的简单变量使用 ??=(例如 `$a ??= 123`): + // 此时 isset 为 false,直接执行赋值。需要提前声明该局部变量, + // 否则 isset 检查会因变量未定义而报错。此处必须声明为 Type::VAR + // (Variant),使其初值为 NULL,从而 isset 在运行时正确判定为 + // false 并执行赋值;若使用原生类型,isset 恒为 true 会导致取到 + // 未初始化的默认值(如 int(0)、空字符串)。 + if ($this->isVarExpr($expr->var) and !$this->hasVar($this->parseIdentifier($expr->var))) { + $this->addLocalVar($this->parseIdentifier($expr->var), Type::VAR); + } + $isset = $this->parseChainedExpr($expr->var, self::OP_ISSET); $var = $this->parseWritableIdentifier($expr->var); @@ -878,9 +889,6 @@ trait AssignOpTrait if ($this->isVarExpr($expr->expr) and !$this->hasVar($right)) { $this->errorUndefinedVariable($expr->expr); } - if ($this->isVarExpr($expr->var) and !$this->hasVar($var)) { - $this->addLocalVar($var, $this->getNormalAssignType($this->detectTypeOfExpr($expr->expr))); - } return '(' . $isset . '?' . $var . ':(' . $var . ' = ' . $right . '))'; } diff --git a/tests/compiler/coalesce/assign-coalesce-undefined-var.phpt b/tests/compiler/coalesce/assign-coalesce-undefined-var.phpt new file mode 100644 index 00000000..4aad8edb --- /dev/null +++ b/tests/compiler/coalesce/assign-coalesce-undefined-var.phpt @@ -0,0 +1,14 @@ +--TEST-- +assign coalesce on undefined variable +--FILE-- + +--EXPECT-- +int(123) +string(3) "foo"