Skip to content

SplObjectStorage iterates over objects#4789

Open
staabm wants to merge 7 commits intophpstan:2.1.xfrom
staabm:bug13985
Open

SplObjectStorage iterates over objects#4789
staabm wants to merge 7 commits intophpstan:2.1.xfrom
staabm:bug13985

Conversation

@staabm
Copy link
Contributor

@staabm staabm commented Jan 20, 2026

closes phpstan/phpstan#13985
closes phpstan/phpstan#14046

partly reverts #4761

@ondrejmirtes
Copy link
Member

I don't get it, why shouldn't it be cached?

@staabm
Copy link
Contributor Author

staabm commented Jan 20, 2026

ClassReflection created via withTypes has properties like isDeprecated, isGeneric, isInternal set to null

grafik

while the one created via getClass contains more information:

grafik

so by caching the withTypes created one, we have less information at hand later on when we respond to a getClassReflection() call with a cached object

@staabm
Copy link
Contributor Author

staabm commented Jan 20, 2026

Hmm no. This doesn't make sense. Will have another look tomorrow

@staabm
Copy link
Contributor Author

staabm commented Jan 21, 2026

had another look but still I am not yet sure about the causation.

the difference between caching and not caching is, that

  • when caching generics ClassReflection for SplObjectStorage the template-type map will be ErrorType, ErrorType which causes lots of if instanceof ErrorType logic to happen and fallbacks are getting evaluated
  • when not caching generics ClassReflection for SplObjectStorage the template-type map will reflect the unresolved types of the phpdoc stub

Copy link
Contributor

@cs278 cs278 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested - fixes phpstan/phpstan#14046 for me

@@ -1746,7 +1746,7 @@ public function getClassReflection(): ?ClassReflection

$classReflection = $reflectionProvider->getClass($this->className);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still cache the classReflection before the withType call ?

Maybe the code could be

if ($this->classReflection === null) {
      $reflectionProvider = ReflectionProviderStaticAccessor::getInstance();
		if (!$reflectionProvider->hasClass($this->className)) {
			return null;
		}
		
		$this->classReflection = $reflectionProvider->getClass($this->className);
}

if ($this->classReflection->isGeneric()) {
     return $this->classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static fn (): Type => new ErrorType())->getTypes()));
}

return $this->classReflection;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatePeriod iterator types no longer understood Errors related to SplObjectStorage in 2.1.34

4 participants