fix(compiler): 修复抽象类和接口的类型处理逻辑

- 移除对抽象类和接口参数类型的限制检查
- 简化对象类型推断逻辑,统一处理所有类类型
- 更新 addObject 方法,阻止为抽象类、接口、内部类创建实例
- 修正参数类型处理中的重复对象添加问题
pull/1/head
韩天峰 3 months ago
parent ee81d116ef
commit 71627fd920
  1. 19
      src/Php/CompilerBase.php
  2. 24
      tests/aot/class/abstract-class-method.phpt
  3. 14
      tests/aot/class/abstract-class.inc

@ -1113,10 +1113,7 @@ 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)) {
if ($argInfo->class) {
$this->addObject($argInfo->name, $argInfo->class);
}
}
@ -1656,10 +1653,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($rightClass) {
if (!$this->hasVar($var)) {
$this->addLocalVar($var, self::TYPE_OBJECT);
// TODO 返回值类型是一个接口,只能作为 var 变量,无法作为 TypedObject
if (!$this->hasInterface($rightClass) and !$this->isAbstractClass($rightClass)) {
$this->addObject($var, $rightClass);
}
$this->addObject($var, $rightClass);
} elseif ($this->isTypedObject($var)) {
$leftClass = $this->getObjectType($var);
// 对象的类不一致,不能互相赋值,必须使用 objval() 对齐类型
@ -2202,8 +2196,12 @@ 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`");
// 接口、抽象类、内部类、非原生类,无法作为 TypedObject 使用
if ($this->hasInterface($class) or
$this->isInternalClass($class) or
$this->isAbstractClass($class) or
!$this->hasClass($class)) {
return;
}
$this->context->objects[$name] = $class;
}
@ -2671,7 +2669,6 @@ class CompilerBase extends \PhpAot\Core\Translator
$type = self::TYPE_VAR;
}
if ($class and !$this->hasInterface($class) and !$this->isAbstractClass($class)) {
$this->addObject($var, $class);
$argInfo->class = $class;
}
return $type;

@ -0,0 +1,24 @@
--TEST--
abstract class and abstract method
--FILE--
<?php
namespace {
use App1\Dog;
use App1\Animal;
function foo(Animal $animal) {
$rs = $animal->speak();
var_dump($rs);
}
function main() {
include __DIR__ . "/abstract-class.inc";
$dog = new Dog("Buddy");
foo($dog);
echo "done\n";
}
}
?>
--EXPECT--
string(4) "woof"
done

@ -0,0 +1,14 @@
<?php
namespace App1 {
interface Speakable {
public function speak(): string;
}
abstract class Animal implements Speakable {
protected string $name;
}
class Dog extends Animal {
public function speak(): string {
return "woof";
}
}
}
Loading…
Cancel
Save