You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Template covariance false positive with nullable type on level < 8 #12008
This shouldn't report an error. The problem is in RuleLevelHelper because it blindly removes null from everything but in case of invariant @template with GenericObjectType this is counter-productive.
A solution would be to somehow employ SimultaneousTypeTraverser instead of TypeTraverser which keeps the context of both $acceptingType and $acceptedType. Then we'd be able to check the @template of the accepting side and decide if null should be removed or not.
Thanks for reporting, I could not understand what's wrong here after updating to v2.0.1:
Method Tests\TestCase::getAppInstance() should return Slim\App<Psr\Container\ContainerInterface|null> but returns Slim\App<Psr\Container\ContainerInterface|null>.
🪪 return.type
💡 Template type TContainerInterface on class Slim\App is not covariant. Learn more: https://phpstan.org/blog/whats-up-with-template-covariant
Just discovered this, and it seems like there is at least 5 issues open for this (maybe you'll want to close some)
cf #9096 (comment)
A solution would be to somehow employ SimultaneousTypeTraverser instead of TypeTraverser which keeps the context of both $acceptingType and $acceptedType. Then we'd be able to check the @template of the accepting side and decide if null should be removed or not.
I tried, but as soon as TypeTraverser is replaced by SimultaneousTypeTraverser, some tests are failing.
For instance when comparing array<string> with list<string|null>, since
traverseSimultaneously with Array&List, Array the early IntersectionType check
if (!$right instanceof self) {
return $this;
}
prevents to keep traversing the array keys/values.
I dunno how to handle this...
The only workaround I found so far would be to have an early check
$acceptingType->accepts($acceptedType)
to remove lot of false positive (is it ok enough for you ?), but it won't fully solve the general issue.
Activity
ondrejmirtes commentedon Nov 12, 2024
A solution would be to somehow employ
SimultaneousTypeTraverserinstead ofTypeTraverserwhich keeps the context of both$acceptingTypeand$acceptedType. Then we'd be able to check the@templateof the accepting side and decide ifnullshould be removed or not.piotr-cz commentedon Nov 13, 2024
Thanks for reporting, I could not understand what's wrong here after updating to v2.0.1:
By the way, it's referring to Slim/App
VincentLanglet commentedon Aug 3, 2025
Just discovered this, and it seems like there is at least 5 issues open for this (maybe you'll want to close some)
cf #9096 (comment)
I tried, but as soon as TypeTraverser is replaced by SimultaneousTypeTraverser, some tests are failing.
For instance when comparing
array<string>withlist<string|null>, sincetraverseSimultaneously with
Array&List, Arraythe early IntersectionType checkprevents to keep traversing the array keys/values.
I dunno how to handle this...
The only workaround I found so far would be to have an early check
to remove lot of false positive (is it ok enough for you ?), but it won't fully solve the general issue.
ondrejmirtes commentedon Aug 5, 2025
@VincentLanglet Please try to do a SimultaneousTypeTraverser proof-of-concept that would solve the GenericObjectType problem with levels.
If it works then we can look into these issues, probably by fixing
IntersectionType::traverseSimultaneously()for lists/arrays etc.VincentLanglet commentedon Aug 6, 2025
Poc opened phpstan/phpstan-src#4210
phpstan-bot commentedon Sep 10, 2026
Closed via merging phpstan/phpstan-src#6392
github-actions commentedon Oct 12, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.