diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index a82f3010649..10b516355d0 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -19,6 +19,7 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\ObjectType; +use PHPStan\Type\RecursionGuard; use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; use PHPStan\Type\UnionType; @@ -95,7 +96,11 @@ public function getReferencedClasses(): array { $classes = parent::getReferencedClasses(); foreach ($this->types as $type) { - foreach ($type->getReferencedClasses() as $referencedClass) { + $referencedClasses = RecursionGuard::runOnObjectIdentity($type, static fn () => $type->getReferencedClasses()); + if ($referencedClasses instanceof ErrorType) { + continue; + } + foreach ($referencedClasses as $referencedClass) { $classes[] = $referencedClass; } } diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index d9f7bf025dd..9020c4b3c4a 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1499,6 +1499,13 @@ public function testBug14324(): void $this->assertNoErrors($errors); } + public function testBug13801(): void + { + // endless loop crash + $errors = $this->runAnalyse(__DIR__ . '/data/bug-13801.php'); + $this->assertNoErrors($errors); + } + /** * @param string[]|null $allAnalysedFiles * @return list diff --git a/tests/PHPStan/Analyser/data/bug-13801.php b/tests/PHPStan/Analyser/data/bug-13801.php new file mode 100644 index 00000000000..5e379c217c7 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-13801.php @@ -0,0 +1,19 @@ + + */ +interface Castable +{ +}