Skip to content

StringableForToStringRector + TypedPropertyRector + string|null = ERROR #6862

@mkopinsky

Description

@mkopinsky

Bug Report

Subject Details
Rector version 0.12.7 (Rector f068fd9)

Minimal PHP Code Causing Issue

https://getrector.org/demo/1ec5bb75-1ea0-6252-b46d-d772a8906bd8

StringableForToStringRector and TypedPropertyRector when combined are throwing an error.

If I run TypedPropertyRector by itself it outputs

    ---------- begin diff ----------
@@ @@
     /**
      * @ORM\Column(type="string", length=255, nullable=true)
      */
-    private $nickname;
+    private ?string $nickname = null;

     public function __toString()
     {
    ----------- end diff -----------

If I run StringableForToStringRector by itself it outputs

    ---------- begin diff ----------
@@ @@
 /**
  * @ORM\Entity(repositoryClass=RectorTestRepository::class)
  */
-class RectorTest
+class RectorTest implements \Stringable
 {
     /**
      * @ORM\Column(type="string", length=255, nullable=true)
@@ @@
      */
     private $nickname;

-    public function __toString()
+    public function __toString(): string
     {
         return $this->nickname;
     }
    ----------- end diff -----------

When combined, they just error

╰─❯ vendor/bin/rector process src/Entity/RectorTest.php --dry-run --debug
[parsing] src/Entity/RectorTest.php
[refactoring] src/Entity/RectorTest.php
    [applying] Rector\Php80\Rector\Class_\StringableForToStringRector
    [applying] Rector\Php74\Rector\Property\TypedPropertyRector
PHP Fatal error:  Uncaught PHPStan\ShouldNotHappenException: Cannot create PHPStan\Type\UnionType with: string, string|null in phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php:33
Stack trace:
#0 phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php(47): PHPStan\Type\UnionType::PHPStan\Type\{closure}()
#1 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterPropertyTypeInferer.php(97): PHPStan\Type\UnionType->__construct(Array)
#2 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer.php(101): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer\GetterPropertyTypeInferer->inferProperty(Object(PhpParser\Node\Stmt\Property))
#3 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer.php(73): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer->getResolvedTypes(Object(PhpParser\Node\Stmt\Property))
#4 <snip>/vendor/rector/rector/rules/Php74/Rector/Property/TypedPropertyRector.php(172): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer->inferProperty(Object(PhpParser\Node\Stmt\Property))
#5 <snip>/vendor/rector/rector/src/Rector/AbstractRector.php(237): Rector\Php74\Rector\Property\TypedPropertyRector->refactor(Object(PhpParser\Node\Stmt\Property))
#6 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(176): Rector\Core\Rector\AbstractRector->enterNode(Object(PhpParser\Node\Stmt\Property))
#7 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#8 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Class_))
#9 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#10 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))
#11 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(85): PhpParser\NodeTraverser->traverseArray(Array)
#12 <snip>/vendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php(56): PhpParser\NodeTraverser->traverse(Array)
#13 <snip>/vendor/rector/rector/src/Application/FileProcessor.php(57): Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser->traverse(Array)
#14 <snip>/vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php(143): Rector\Core\Application\FileProcessor->refactor(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#15 <snip>/vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php(103): Rector\Core\Application\FileProcessor\PhpFileProcessor->refactorNodesWithRectors(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#16 <snip>/vendor/rector/rector/src/Application/ApplicationFileProcessor.php(96): Rector\Core\Application\FileProcessor\PhpFileProcessor->process(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#17 <snip>/vendor/rector/rector/src/Application/ApplicationFileProcessor.php(74): Rector\Core\Application\ApplicationFileProcessor->processFiles(Array, Object(Rector\Core\ValueObject\Configuration))
#18 <snip>/vendor/rector/rector/src/Console/Command/ProcessCommand.php(165): Rector\Core\Application\ApplicationFileProcessor->run(Array, Object(Rector\Core\ValueObject\Configuration))
#19 <snip>/vendor/rector/rector/vendor/symfony/console/Command/Command.php(296): Rector\Core\Console\Command\ProcessCommand->execute(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#20 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(897): RectorPrefix20211209\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#21 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(300): RectorPrefix20211209\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Core\Console\Command\ProcessCommand), Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#22 <snip>/vendor/rector/rector/src/Console/ConsoleApplication.php(71): RectorPrefix20211209\Symfony\Component\Console\Application->doRun(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#23 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(196): Rector\Core\Console\ConsoleApplication->doRun(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#24 <snip>/vendor/rector/rector/bin/rector.php(56): RectorPrefix20211209\Symfony\Component\Console\Application->run()
#25 <snip>/vendor/rector/rector/bin/rector(5): require_once('/Users/kopinsky...')
#26 {main}
  thrown in phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php on line 33
Fatal error: Uncaught PHPStan\ShouldNotHappenException: Cannot create PHPStan\Type\UnionType with: string, string|null in phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php:33
Stack trace:
#0 phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php(47): PHPStan\Type\UnionType::PHPStan\Type\{closure}()
#1 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterPropertyTypeInferer.php(97): PHPStan\Type\UnionType->__construct(Array)
#2 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer.php(101): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer\GetterPropertyTypeInferer->inferProperty(Object(PhpParser\Node\Stmt\Property))
#3 <snip>/vendor/rector/rector/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer.php(73): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer->getResolvedTypes(Object(PhpParser\Node\Stmt\Property))
#4 <snip>/vendor/rector/rector/rules/Php74/Rector/Property/TypedPropertyRector.php(172): Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer->inferProperty(Object(PhpParser\Node\Stmt\Property))
#5 <snip>/vendor/rector/rector/src/Rector/AbstractRector.php(237): Rector\Php74\Rector\Property\TypedPropertyRector->refactor(Object(PhpParser\Node\Stmt\Property))
#6 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(176): Rector\Core\Rector\AbstractRector->enterNode(Object(PhpParser\Node\Stmt\Property))
#7 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#8 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Class_))
#9 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#10 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))
#11 <snip>/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(85): PhpParser\NodeTraverser->traverseArray(Array)
#12 <snip>/vendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php(56): PhpParser\NodeTraverser->traverse(Array)
#13 <snip>/vendor/rector/rector/src/Application/FileProcessor.php(57): Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser->traverse(Array)
#14 <snip>/vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php(143): Rector\Core\Application\FileProcessor->refactor(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#15 <snip>/vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php(103): Rector\Core\Application\FileProcessor\PhpFileProcessor->refactorNodesWithRectors(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#16 <snip>/vendor/rector/rector/src/Application/ApplicationFileProcessor.php(96): Rector\Core\Application\FileProcessor\PhpFileProcessor->process(Object(Rector\Core\ValueObject\Application\File), Object(Rector\Core\ValueObject\Configuration))
#17 <snip>/vendor/rector/rector/src/Application/ApplicationFileProcessor.php(74): Rector\Core\Application\ApplicationFileProcessor->processFiles(Array, Object(Rector\Core\ValueObject\Configuration))
#18 <snip>/vendor/rector/rector/src/Console/Command/ProcessCommand.php(165): Rector\Core\Application\ApplicationFileProcessor->run(Array, Object(Rector\Core\ValueObject\Configuration))
#19 <snip>/vendor/rector/rector/vendor/symfony/console/Command/Command.php(296): Rector\Core\Console\Command\ProcessCommand->execute(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#20 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(897): RectorPrefix20211209\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#21 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(300): RectorPrefix20211209\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Core\Console\Command\ProcessCommand), Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#22 <snip>/vendor/rector/rector/src/Console/ConsoleApplication.php(71): RectorPrefix20211209\Symfony\Component\Console\Application->doRun(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#23 <snip>/vendor/rector/rector/vendor/symfony/console/Application.php(196): Rector\Core\Console\ConsoleApplication->doRun(Object(RectorPrefix20211209\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix20211209\Symfony\Component\Console\Output\ConsoleOutput))
#24 <snip>/vendor/rector/rector/bin/rector.php(56): RectorPrefix20211209\Symfony\Component\Console\Application->run()
#25 <snip>/vendor/rector/rector/bin/rector(5): require_once('/Users/kopinsky...')
#26 {main}
  thrown in phar://<snip>/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/src/Type/UnionType.php on line 33

Expected Behaviour

Honestly, I'm not familiar enough with PHP8 to say what the right answer is, when the __toString returns something that is technically nullable. Maybe it should just skip it? But erroring certainly isn't the right answer ;-)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions