diff --git a/src/Php/ArgInfo.php b/src/Php/ArgInfo.php index 35fae7eb..54dde567 100644 --- a/src/Php/ArgInfo.php +++ b/src/Php/ArgInfo.php @@ -16,6 +16,7 @@ class ArgInfo public string $type; public string $default = ''; public ?Expr $defaultValue = null; + public string $class = ''; public bool $byRef = false; public bool $variadic = false; public bool $nullable = false; diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 7450781c..b77a7ffd 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1064,13 +1064,13 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->method and $name == 'this_') { $this->fatalError($param, 'Cannot use `$this` as parameter of class method'); } - $type = $this->parseParameterType($param, $name); + $argInfo = new ArgInfo(); + $type = $this->parseParameterType($param, $argInfo, $name); if ($param->variadic) { $list[] = self::TYPE_ARRAY . ' ' . $name; } else { $list[] = $type . ' ' . $name; } - $argInfo = new ArgInfo(); $argInfo->name = $name; $argInfo->type = $type; $argInfo->byRef = $param->byRef; @@ -1447,6 +1447,9 @@ class CompilerBase extends \PhpAot\Core\Translator $this->fatalError($left, 'Cannot use [] for strings'); } } + if ($this->isScalar($right) or $this->isVarExpr($right)) { + return $this->parseAssignArrayDim($left, $right); + } } return $var . ' = ' . $this->convertExprType($expr, $this->detectExprType($left), $this->detectExprType($right)); @@ -1980,7 +1983,7 @@ class CompilerBase extends \PhpAot\Core\Translator '}'; } - protected function parseParameterType(Node\Param $param, string $var): string + protected function parseParameterType(Node\Param $param, ArgInfo $argInfo, string $var): string { if ($param->byRef) { return self::TYPE_REF; @@ -1998,7 +2001,9 @@ class CompilerBase extends \PhpAot\Core\Translator } elseif (isset($this->zendTypeMap[$typeName])) { return $this->getTypeFromZendType($typeName); } else { - $this->addObject($var, $this->getNamespacedClassName($typeName)); + $class = $this->getNamespacedClassName($typeName); + $this->addObject($var, $class); + $argInfo->class = $class; return self::TYPE_OBJECT; } } @@ -3257,7 +3262,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->functionDef->returnType; } - protected function getTypeConvertedArg($arg, ArgInfo $argInfo): string + protected function getTypeConvertedArg(Node\Arg $arg, ArgInfo $argInfo): string { $expr = $this->parseArg($arg); $type = $this->detectExprType($arg->value); @@ -3267,6 +3272,13 @@ class CompilerBase extends \PhpAot\Core\Translator } if ($argInfo->type === self::TYPE_OBJECT) { + $object = $this->parseVariable($arg->value); + if ($this->isVarExpr($arg->value) and $this->isTypedObject($object)) { + $class = $this->getObjectType($object); + if ($argInfo->class and $class != $argInfo->class) { + $this->fatalError($arg, "Argument `{$argInfo->name}` must be an instance of `{$argInfo->class}`, `{$class}` given"); + } + } return $this->convertObjectExpr($expr); } diff --git a/tests/aot/type_hits/001.phpt b/tests/aot/type_hits/001.phpt new file mode 100644 index 00000000..a695560b --- /dev/null +++ b/tests/aot/type_hits/001.phpt @@ -0,0 +1,37 @@ +--TEST-- +type hits +--FILE-- +name = "John"; + $obj->age = 20; + foo($obj); + + $arr = new ArrayObject(); + $name = "John"; + $arr["name"] = $name; + $arr["age"] = 20; + foo($arr); +} +?> +--EXPECT-- +object(stdClass)#1 (2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) +} +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + array(2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) + } +} diff --git a/tests/aot/type_hits/002.phpt b/tests/aot/type_hits/002.phpt new file mode 100644 index 00000000..89427c55 --- /dev/null +++ b/tests/aot/type_hits/002.phpt @@ -0,0 +1,23 @@ +--TEST-- +type hits +--FILE-- +name = "John"; + $obj->age = 20; + foo($obj); +} +?> +--EXPECT-- +object(stdClass)#1 (2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) +}