diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index a579201c..d50af5f2 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1039,6 +1039,12 @@ class CompilerBase extends \PhpAot\Core\Translator } foreach ($this->functionDef->argInfoList as $argInfo) { $this->addArgument($argInfo->name, $argInfo->type); + if ($argInfo->class + and !$this->isAbstractClass($argInfo->class) + and !$this->hasInterface($argInfo->class) + and !$this->isInternalClass($argInfo->class)) { + $this->addObject($argInfo->name, $argInfo->class); + } } $stmts = ''; @@ -1248,6 +1254,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseStmts(array $stmts): string { + $this->context->enterScope(); $lines = []; $inLoopTop = $this->context->inLoop; $last = array_key_last($stmts); @@ -1351,6 +1358,7 @@ class CompilerBase extends \PhpAot\Core\Translator foreach ($lines as $line) { $code .= $this->getIndent() . $line . PHP_EOL; } + $this->context->leaveScope(); return $code; } @@ -1523,6 +1531,9 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->hasVar($var)) { $this->fatalError($left, "Cannot re-assign `\${$var}` to std::array"); } + if ($this->context->scopeLevel > 1) { + $this->fatalError($left, 'Must create std::array in the top-level scope of the function'); + } $this->addLocalVar($var, self::TYPE_STD_ARRAY); return $this->parseStdArray($var, $right); } else { @@ -1881,6 +1892,9 @@ class CompilerBase extends \PhpAot\Core\Translator protected function addObject(string $name, string $class): void { + if ($this->hasInterface($class) or $this->isAbstractClass($class)) { + $this->error("Cannot create an instance of abstract/interface `$class`"); + } $this->context->objects[$name] = $class; } @@ -3784,7 +3798,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function isInheritedFrom(string $class, string $expected): bool { $internal = ($this->isInternalClass($expected) or $this->isInternalInterface($expected)); - $isInterface = $this->hasInterface($expected); + $isInterface = ($this->hasInterface($expected) or $this->isInternalInterface($expected)); // 类不存在,说明这是一个动态类,跳过静态检查,需要运行时检查 if (!$this->hasClass($class)) { return true; diff --git a/src/Php/Context/FunctionContext.php b/src/Php/Context/FunctionContext.php index b8bf5fd0..2e64a0a1 100644 --- a/src/Php/Context/FunctionContext.php +++ b/src/Php/Context/FunctionContext.php @@ -39,6 +39,11 @@ class FunctionContext public array $beforeStmtLines = []; public array $afterStmtLines = []; public array $objectProps; + public int $scopeLevel = 0; + /** + * @var array + */ + public array $scopeLayouts = []; public function __construct() { @@ -49,8 +54,22 @@ class FunctionContext $this->objectProps = []; $this->ceWrappers = []; $this->tmpVarIndex = 0; + $this->scopeLayouts = []; + $this->scopeLevel = 0; $this->inLoop = false; $this->inClosure = false; $this->inAssignExpr = false; } + + public function enterScope(): void + { + $this->scopeLayouts[$this->scopeLevel] = new ScopeContext(); + $this->scopeLevel++; + } + + public function leaveScope(): void + { + unset($this->scopeLayouts[$this->scopeLevel]); + $this->scopeLevel--; + } } diff --git a/src/Php/Context/ScopeContext.php b/src/Php/Context/ScopeContext.php new file mode 100644 index 00000000..39c3cb6a --- /dev/null +++ b/src/Php/Context/ScopeContext.php @@ -0,0 +1,8 @@ +bar(); +} + +function main() { + $o = new Foo1123; + foo($o); +} +?> +--EXPECTF-- +string(12) "Foo1123::bar" \ No newline at end of file diff --git a/tests/aot/type_hits/006.phpt b/tests/aot/type_hits/006.phpt new file mode 100644 index 00000000..b52e1170 --- /dev/null +++ b/tests/aot/type_hits/006.phpt @@ -0,0 +1,22 @@ +--TEST-- +type hits +--FILE-- + +--EXPECT-- +string(11) "Hello World" \ No newline at end of file