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
pull/48/head
韩天峰 3 weeks ago
parent bd6335ec3b
commit e1018ca87e
  1. 8
      src/Generator/AnonClassGenerator.php
  2. 17
      tests/compiler/anon_class/005.phpt

@ -177,6 +177,14 @@ trait AnonClassGenerator
$class = $this->classStack[count($this->classStack) - 1] ?? null; $class = $this->classStack[count($this->classStack) - 1] ?? null;
if ($class !== null && $this->compiler->shouldAddMixedReturnToEmbeddedClassMethod($class, $node)) { if ($class !== null && $this->compiler->shouldAddMixedReturnToEmbeddedClassMethod($class, $node)) {
$node->returnType = new Identifier('mixed'); $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; return null;

@ -14,16 +14,23 @@ namespace AnonymousClassSupport {
function accepts(Subject $value): bool { function accepts(Subject $value): bool {
return true; return true;
} }
class Visitor {
public function inspect(object $value) {
return null;
}
}
} }
namespace AnonymousClassConsumer { namespace AnonymousClassConsumer {
use AnonymousClassSupport\Marker as ImportedMarker; use AnonymousClassSupport\Marker as ImportedMarker;
use AnonymousClassSupport\Subject as ImportedSubject; use AnonymousClassSupport\Subject as ImportedSubject;
use AnonymousClassSupport\Visitor as ImportedVisitor;
use const AnonymousClassSupport\FLAG as IMPORTED_FLAG; use const AnonymousClassSupport\FLAG as IMPORTED_FLAG;
use function AnonymousClassSupport\accepts as imported_accepts; use function AnonymousClassSupport\accepts as imported_accepts;
function main(): void { function main(): void {
$visitor = new class('ready') { $visitor = new class('ready') extends ImportedVisitor {
public function __construct(private readonly string $state) {} public function __construct(private readonly string $state) {}
public function accepts(object $value): bool { public function accepts(object $value): bool {
@ -33,9 +40,16 @@ namespace AnonymousClassConsumer {
&& imported_accepts($value) && imported_accepts($value)
&& $this->state === 'ready'; && $this->state === 'ready';
} }
public function inspect(object $value) {
if ($value instanceof ImportedSubject) {
return 'subject';
}
}
}; };
var_dump($visitor->accepts(new ImportedSubject())); var_dump($visitor->accepts(new ImportedSubject()));
var_dump($visitor->inspect(new \stdClass()));
} }
} }
@ -47,3 +61,4 @@ namespace {
?> ?>
--EXPECT-- --EXPECT--
bool(true) bool(true)
NULL

Loading…
Cancel
Save