From e1018ca87e770c1e5914e38bef9028e2b110a644 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 12 Aug 2026 17:41:35 +0800 Subject: [PATCH] fix(anon-class): handle null return in anonymous class methods - Add explicit null return statement when mixed return type is added to anonymous class methods - Extend anonymous class with ImportedVisitor base class in test case - Add inspect method implementation in anonymous class to check object instances - Update expected test output to include NULL result - Add proper visitor class with inspect method in test namespace - Include necessary use statements for Visitor class in anonymous class consumer tests --- src/Generator/AnonClassGenerator.php | 8 ++++++++ tests/compiler/anon_class/005.phpt | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Generator/AnonClassGenerator.php b/src/Generator/AnonClassGenerator.php index 6152bc86..c98eb024 100644 --- a/src/Generator/AnonClassGenerator.php +++ b/src/Generator/AnonClassGenerator.php @@ -177,6 +177,14 @@ trait AnonClassGenerator $class = $this->classStack[count($this->classStack) - 1] ?? null; if ($class !== null && $this->compiler->shouldAddMixedReturnToEmbeddedClassMethod($class, $node)) { $node->returnType = new Identifier('mixed'); + // An implicit fallthrough returns null in PHP. Once the + // compatibility return type is made explicit, PHP requires + // an explicit value on that path as well. + if ($node->stmts !== null) { + $node->stmts[] = new Node\Stmt\Return_( + new Node\Expr\ConstFetch(new Name('null')), + ); + } } } return null; diff --git a/tests/compiler/anon_class/005.phpt b/tests/compiler/anon_class/005.phpt index c3650797..c44495d4 100644 --- a/tests/compiler/anon_class/005.phpt +++ b/tests/compiler/anon_class/005.phpt @@ -14,16 +14,23 @@ namespace AnonymousClassSupport { function accepts(Subject $value): bool { return true; } + + class Visitor { + public function inspect(object $value) { + return null; + } + } } namespace AnonymousClassConsumer { use AnonymousClassSupport\Marker as ImportedMarker; use AnonymousClassSupport\Subject as ImportedSubject; + use AnonymousClassSupport\Visitor as ImportedVisitor; use const AnonymousClassSupport\FLAG as IMPORTED_FLAG; use function AnonymousClassSupport\accepts as imported_accepts; function main(): void { - $visitor = new class('ready') { + $visitor = new class('ready') extends ImportedVisitor { public function __construct(private readonly string $state) {} public function accepts(object $value): bool { @@ -33,9 +40,16 @@ namespace AnonymousClassConsumer { && imported_accepts($value) && $this->state === 'ready'; } + + public function inspect(object $value) { + if ($value instanceof ImportedSubject) { + return 'subject'; + } + } }; var_dump($visitor->accepts(new ImportedSubject())); + var_dump($visitor->inspect(new \stdClass())); } } @@ -47,3 +61,4 @@ namespace { ?> --EXPECT-- bool(true) +NULL