diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index 43ddf267a..a6cf1d78f 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -234,6 +234,16 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour $this->functionlike_node_scanners[] = $functionlike_node_scanner; + if ($classlike_storage + && !$classlike_storage->is_interface + && $this->codebase->php_major_version >= 8 + && $node instanceof PhpParser\Node\Stmt\ClassMethod + && strtolower($node->name->name) === '__tostring' + ) { + $classlike_storage->class_implements['stringable'] = 'Stringable'; + $this->codebase->scanner->queueClassLikeForScanning('Stringable'); + } + if (!$this->scan_deep) { return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } diff --git a/tests/ToStringTest.php b/tests/ToStringTest.php index bdeb6f70e..5579afbfd 100644 --- a/tests/ToStringTest.php +++ b/tests/ToStringTest.php @@ -169,6 +169,21 @@ class ToStringTest extends TestCase [], '8.0' ], + 'implicitStringable' => [ + ' 'UndefinedGlobalVariable', ], + 'implicitStringableDisallowed' => [ + ' 'InvalidArgument', + [], + '7.4', + ], ]; } }