From a462b80747e91c632ea6642565f7766efae3723e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 20 Jan 2026 14:58:18 +0100 Subject: [PATCH 1/5] SplObjectStorage iterates over objects --- tests/PHPStan/Analyser/nsrt/bug-13985.php | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-13985.php diff --git a/tests/PHPStan/Analyser/nsrt/bug-13985.php b/tests/PHPStan/Analyser/nsrt/bug-13985.php new file mode 100644 index 0000000000..0224007d36 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13985.php @@ -0,0 +1,32 @@ + $value) { + assertType('int', $key); + assertType('object', $value); + } + } +} + +class X {} + +/** + * @param SplObjectStorage $splObjectStorage + * @return void + */ +function genericExample(SplObjectStorage $splObjectStorage): void +{ + foreach ($splObjectStorage as $key => $value) { + assertType('int', $key); + assertType('Bug13985\X', $value); + } + assertType('int', $splObjectStorage->getInfo()); + +} From 728ba27df80df988c458b26ed506039d54fd28ca Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 20 Jan 2026 15:08:50 +0100 Subject: [PATCH 2/5] Revert "Cache ClassReflections" reverts https://github.com/phpstan/phpstan-src/commit/4a143bdda18c535d66ea5afbcea885c7cce63abd --- src/Type/ObjectType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 3e755bab60..ca75971914 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1746,10 +1746,10 @@ public function getClassReflection(): ?ClassReflection $classReflection = $reflectionProvider->getClass($this->className); if ($classReflection->isGeneric()) { - return $this->classReflection = $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes())); + return $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes())); } - return $this->classReflection = $classReflection; + return $classReflection; } public function getAncestorWithClassName(string $className): ?self From b12ad34243904aa099d9a3bfe3707caea087bae4 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 20 Jan 2026 15:16:46 +0100 Subject: [PATCH 3/5] Update ObjectType.php --- src/Type/ObjectType.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index ca75971914..3e2960a67c 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1746,10 +1746,11 @@ public function getClassReflection(): ?ClassReflection $classReflection = $reflectionProvider->getClass($this->className); if ($classReflection->isGeneric()) { + // withTypes creates a new object, don't cache it in $this->classReflection return $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes())); } - return $classReflection; + return $this->classReflection = $classReflection; } public function getAncestorWithClassName(string $className): ?self From 632dba9beb9d9fd9ab0eb0970a857d787b91c3d8 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 20 Jan 2026 15:16:54 +0100 Subject: [PATCH 4/5] Update ObjectType.php --- src/Type/ObjectType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 3e2960a67c..0e7626426d 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1746,7 +1746,7 @@ public function getClassReflection(): ?ClassReflection $classReflection = $reflectionProvider->getClass($this->className); if ($classReflection->isGeneric()) { - // withTypes creates a new object, don't cache it in $this->classReflection + // withTypes() creates a new object, don't cache it in $this->classReflection return $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes())); } From ed702013c36314290a6c95043e2b84b9375858ab Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 20 Jan 2026 19:13:46 +0100 Subject: [PATCH 5/5] Update ObjectType.php --- src/Type/ObjectType.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 0e7626426d..b69fd0e5d1 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1746,7 +1746,6 @@ public function getClassReflection(): ?ClassReflection $classReflection = $reflectionProvider->getClass($this->className); if ($classReflection->isGeneric()) { - // withTypes() creates a new object, don't cache it in $this->classReflection return $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes())); }