diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index 2c281f58ca..de0981858d 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -66,6 +66,9 @@ final class FileTypeMapper /** @var array */ private array $inProcess = []; + /** @var array */ + private array $inProcessNameScopes = []; + /** @var array */ private array $resolvedPhpDocBlockCache = []; @@ -200,6 +203,9 @@ public function getNameScope( { $nameScopeKey = $this->getNameScopeKey($fileName, $className, $traitName, $functionName); if (isset($this->inProcess[$nameScopeKey])) { + if (isset($this->inProcessNameScopes[$nameScopeKey])) { + return $this->inProcessNameScopes[$nameScopeKey]; + } throw new NameScopeAlreadyBeingCreatedException(); } @@ -288,6 +294,8 @@ public function getNameScope( continue; } + $this->inProcessNameScopes[$nameScopeKey] = $nameScope; + $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($parent->getTemplatePhpDocNodes(), $nameScope); $templateTypeMap = new TemplateTypeMap(array_map(static fn (TemplateTag $tag): Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap, $templateTags); @@ -319,6 +327,7 @@ public function getNameScope( ); } finally { unset($this->inProcess[$nameScopeKey]); + unset($this->inProcessNameScopes[$nameScopeKey]); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-11314.php b/tests/PHPStan/Analyser/nsrt/bug-11314.php new file mode 100644 index 0000000000..e541bb8691 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11314.php @@ -0,0 +1,51 @@ +breed); + + $cat2 = new Cat2(); + assertType("'British Shorthair'|'Maine Coon'|'Siamese'", $cat2->breed); + + $cat3 = new Cat3(); + assertType("'British Shorthair'|'Maine Coon'|'Siamese'", $cat3->breed); +};