diff --git a/tests/PHPStan/Analyser/nsrt/bug-14804.php b/tests/PHPStan/Analyser/nsrt/bug-14804.php new file mode 100644 index 0000000000..0ab2307aa6 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14804.php @@ -0,0 +1,83 @@ + */ + private array $registry = []; + + /** @var array */ + private array $persistentDependencies = []; + + /** @var array $arguments): object)> */ + private array $initializers = []; + + /** @var array */ + private array $resolving = []; + + /** + * @template TClassName of object + * @param class-string $className + * @return TClassName + */ + public function resolve(string $className, array $arguments = []): object + { + $lifecycle = $this->registry[$className] ?? Lifecycle::TRANSIENT; + + if ( + $lifecycle === Lifecycle::PERSISTENT && + isset($this->persistentDependencies[$className]) + ) { + /** @var TClassName */ + return $this->persistentDependencies[$className]; + } + + if (isset($this->resolving[$className])) { + throw new \Exception(); + } + + $this->resolving[$className] = true; + + try { + if (isset($this->initializers[$className])) { + assertType('$this(Bug14804\Container)', $this); + assertType('Bug14804\Lifecycle::PERSISTENT|Bug14804\Lifecycle::TRANSIENT', $lifecycle); + + /** @var TClassName $instance */ + $instance = ($this->initializers[$className])($this, $arguments); + + if ($lifecycle === Lifecycle::PERSISTENT) { + assertType('Bug14804\Lifecycle::PERSISTENT', $lifecycle); + assertType('$this(Bug14804\Container)', $this); + + unset($this->initializers[$className]); + $this->persistentDependencies[$className] = $instance; + } + + return $instance; + } + + throw new \Exception(); + } finally { + unset($this->resolving[$className]); + } + } + +}