fix(parser): 修复引用赋值时的类型推断错误

pull/14/head
韩天峰 2 months ago
parent ac5bfa6c68
commit 5ee74b2d9d
  1. 16
      src/Php/Parser/AssignOpTrait.php
  2. 59
      tests/aot/ref/basic.phpt

@ -145,9 +145,10 @@ trait AssignOpTrait
}
$propertyWriteTarget = $this->preparePropertyWriteTarget($left);
$finalVarType = $type = $this->detectTypeOfExpr($right);
$type = $this->detectTypeOfExpr($right);
$finalVarType = $this->getNormalAssignType($type);
if ($type === self::TYPE_VOID) {
$finalVarType = $type = self::TYPE_VAR;
$type = self::TYPE_VAR;
}
if ($this->isVarExpr($left)) {
@ -239,6 +240,7 @@ trait AssignOpTrait
} elseif ($this->isVarExpr($right)) {
$rightVar = $this->parseIdentifier($right);
$type = $this->isStdContainer($rightVar) ? self::TYPE_ARRAY : $this->getVarType($rightVar);
$finalVarType = $this->getNormalAssignType($type);
if ($this->isTypedObject($rightVar) and $this->isTypedObject($var)) {
$leftClass = $this->getObjectType($var);
$rightClass = $this->getObjectType($rightVar);
@ -247,7 +249,8 @@ trait AssignOpTrait
}
// 变量第一次被赋值,确定其类型,由于 PHP 的变量作用域是 function 级的,在 for/while 块中声明的变量,可以在块外使用
if (!$this->hasVar($var)) {
$finalVarType = $this->isNativeType($type) ? $this->getNativeType($type) : $type;
$finalVarType = $this->getNormalAssignType($type);
$finalVarType = $this->isNativeType($finalVarType) ? $this->getNativeType($finalVarType) : $finalVarType;
$this->addLocalVar($var, $finalVarType);
} else {
$finalVarType = $this->getVarType($var);
@ -597,9 +600,14 @@ trait AssignOpTrait
$this->errorUndefinedVariable($expr->expr);
}
if ($this->isVarExpr($expr->var) and !$this->hasVar($var)) {
$this->addLocalVar($var, $this->detectTypeOfExpr($expr->expr));
$this->addLocalVar($var, $this->getNormalAssignType($this->detectTypeOfExpr($expr->expr)));
}
return '(' . $isset . '?' . $var . ':(' . $var . ' = ' . $right . '))';
}
protected function getNormalAssignType(string $type): string
{
return $type === self::TYPE_REF || $type === self::TYPE_VOID ? self::TYPE_VAR : $type;
}
}

@ -0,0 +1,59 @@
--TEST--
ref: basic
--FILE--
<?php
function main()
{
require __DIR__ . '/../../../src/Assert.php';
$a = [1, 2, 3];
$b = &$a;
$b[] = 5;
$c = &$b;
$c[] = 6;
Assert::eq(count($a), 5);
Assert::eq(count($b), 5);
Assert::eq(count($c), 5);
$array = [1, 2, 3];
$ref = &$array;
$ref[1] = 2026;
$value = $ref;
$value[2] = 1999;
var_dump($array, $value);
$value = 'done';
var_dump($array, $value);
}
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2026)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2026)
[2]=>
int(1999)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2026)
[2]=>
int(3)
}
string(4) "done"
Loading…
Cancel
Save