From d919ee280caa1ca22dbb3fc75cc0e8d0762a9629 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Mon, 30 Mar 2026 14:02:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(php):=20=E4=BF=AE=E5=A4=8D=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1=E7=B1=BB=E6=96=B9=E6=B3=95=E8=B0=83=E7=94=A8=E5=92=8C?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E5=8C=96=E9=94=99=E8=AF=AF=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了抽象类不能被实例化的检查,在编译时抛出错误 - 修复了方法准备逻辑,确保抽象方法在非抽象类中的正确验证 - 更新了测试期望输出以匹配新的错误格式 - 优化了错误堆栈跟踪的显示格式 --- src/Php/CompilerBase.php | 6 ++++++ src/Php/Preprocessor.php | 8 ++++++-- tests/core/classes/abstract.phpt | 9 ++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index d966edf5..c607faf6 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -2921,6 +2921,12 @@ class CompilerBase extends \PhpAot\Core\Translator $cePtr = 'php_get_called_ce(this_)'; } else { $className = $this->getNamespacedClassName($className); + if ($this->hasNativeClass($className)) { + $classDef = $this->getClassDef($className); + if ($classDef->flags & Modifiers::ABSTRACT) { + $this->fatalError($expr, "abstract class `$className` cannot be instantiated"); + } + } $cePtr = $this->getClassEntryPtr($className); } } else { diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 6beffb06..f3d8ada9 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -225,7 +225,7 @@ class Preprocessor extends CompilerBase case 'Stmt_EnumCase': break; case 'Stmt_ClassMethod': - $this->prepareMethod($v); + $this->prepareMethod($v, $class); break; case 'Stmt_Expression': $this->foundStrayCode($v); @@ -240,11 +240,15 @@ class Preprocessor extends CompilerBase return $code; } - protected function prepareMethod(Node\Stmt\ClassMethod $v): void + protected function prepareMethod(Node\Stmt\ClassMethod $v, Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): void { $abstract = $v->flags & Modifiers::ABSTRACT; if (!$abstract) { $this->prepareFunction($v) . PHP_EOL; + } else { + if (!($class->flags & Modifiers::ABSTRACT)) { + $this->fatalError($v, "Class {$this->class} cannot override non-abstract method {$v->name}"); + } } $fullClassName = $this->getFullClassName(); diff --git a/tests/core/classes/abstract.phpt b/tests/core/classes/abstract.phpt index 14af18f9..fec3f4b3 100644 --- a/tests/core/classes/abstract.phpt +++ b/tests/core/classes/abstract.phpt @@ -27,9 +27,8 @@ function main() { --EXPECTF-- Call to function show() -Fatal error: Uncaught Error: Cannot call abstract method fail::show() in %s:%d +Fatal error: Uncaught Error: Cannot call abstract method fail::show() in %s Stack trace: -#0 [internal function]: pass->error() -#1 Unknown(0) : %s -#2 {main} - thrown in %s on line %d +#0 Unknown(0) : %s +#1 {main} + thrown in Unknown(0) : %s