diff --git a/config/set/php/php80.yaml b/config/set/php/php80.yaml
index 9c954f19c8f..48908e8f551 100644
--- a/config/set/php/php80.yaml
+++ b/config/set/php/php80.yaml
@@ -3,3 +3,4 @@ services:
Rector\Php80\Rector\NotIdentical\StrContainsRector: null
Rector\Php80\Rector\Identical\StrStartsWithRector: null
Rector\Php80\Rector\Identical\StrEndsWithRector: null
+ Rector\Php80\Rector\Class_\StringableForToStringRector: null
diff --git a/docs/AllRectorsOverview.md b/docs/AllRectorsOverview.md
index 5abb5d6144c..38faff3a76c 100644
--- a/docs/AllRectorsOverview.md
+++ b/docs/AllRectorsOverview.md
@@ -1,4 +1,4 @@
-# All 501 Rectors Overview
+# All 502 Rectors Overview
- [Projects](#projects)
- [General](#general)
@@ -7915,6 +7915,27 @@ Change helper functions to str_starts_with()
+### `StringableForToStringRector`
+
+- class: [`Rector\Php80\Rector\Class_\StringableForToStringRector`](/../master/rules/php80/src/Rector/Class_/StringableForToStringRector.php)
+- [test fixtures](/../master/rules/php80/tests/Rector/Class_/StringableForToStringRector/Fixture)
+
+Add `Stringable` interface to classes with `__toString()` method
+
+```diff
+-class SomeClass
++class SomeClass implements Stringable
+ {
+- public function __toString()
++ public function __toString(): string
+ {
+ return 'I can stringz';
+ }
+ }
+```
+
+
+
### `UnionTypesRector`
- class: [`Rector\Php80\Rector\FunctionLike\UnionTypesRector`](/../master/rules/php80/src/Rector/FunctionLike/UnionTypesRector.php)
diff --git a/rules/php80/src/Rector/Class_/StringableForToStringRector.php b/rules/php80/src/Rector/Class_/StringableForToStringRector.php
new file mode 100644
index 00000000000..889deea5edc
--- /dev/null
+++ b/rules/php80/src/Rector/Class_/StringableForToStringRector.php
@@ -0,0 +1,99 @@
+classManipulator = $classManipulator;
+ }
+
+ public function getDefinition(): RectorDefinition
+ {
+ return new RectorDefinition('Add `Stringable` interface to classes with `__toString()` method', [
+ new CodeSample(
+ <<<'PHP'
+class SomeClass
+{
+ public function __toString()
+ {
+ return 'I can stringz';
+ }
+}
+PHP
+,
+ <<<'PHP'
+class SomeClass implements Stringable
+{
+ public function __toString(): string
+ {
+ return 'I can stringz';
+ }
+}
+PHP
+
+ ),
+ ]);
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getNodeTypes(): array
+ {
+ return [Class_::class];
+ }
+
+ /**
+ * @param Class_ $node
+ */
+ public function refactor(Node $node): ?Node
+ {
+ $toStringClassMethod = $node->getMethod('__toString');
+ if ($toStringClassMethod === null) {
+ return null;
+ }
+
+ if ($this->classManipulator->hasInterface($node, self::STRINGABLE)) {
+ return null;
+ }
+
+ // add interface
+ $node->implements[] = new FullyQualified(self::STRINGABLE);
+
+ // add return type
+
+ if ($toStringClassMethod->returnType === null) {
+ $toStringClassMethod->returnType = new Name('string');
+ }
+
+ return $node;
+ }
+}
diff --git a/rules/php80/tests/Rector/Class_/StringableForToStringRector/Fixture/fixture.php.inc b/rules/php80/tests/Rector/Class_/StringableForToStringRector/Fixture/fixture.php.inc
new file mode 100644
index 00000000000..ae2495e6767
--- /dev/null
+++ b/rules/php80/tests/Rector/Class_/StringableForToStringRector/Fixture/fixture.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules/php80/tests/Rector/Class_/StringableForToStringRector/StringableForToStringRectorTest.php b/rules/php80/tests/Rector/Class_/StringableForToStringRector/StringableForToStringRectorTest.php
new file mode 100644
index 00000000000..8591e5c3013
--- /dev/null
+++ b/rules/php80/tests/Rector/Class_/StringableForToStringRector/StringableForToStringRectorTest.php
@@ -0,0 +1,30 @@
+doTestFile($file);
+ }
+
+ public function provideData(): Iterator
+ {
+ return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
+ }
+
+ protected function getRectorClass(): string
+ {
+ return StringableForToStringRector::class;
+ }
+}