Skip to content

Avoid false error on is_subclass_of#4472

Open
VincentLanglet wants to merge 4 commits intophpstan:2.1.xfrom
VincentLanglet:isSubClass
Open

Avoid false error on is_subclass_of#4472
VincentLanglet wants to merge 4 commits intophpstan:2.1.xfrom
VincentLanglet:isSubClass

Conversation

@VincentLanglet
Copy link
Contributor

@VincentLanglet VincentLanglet commented Oct 23, 2025

@VincentLanglet VincentLanglet marked this pull request as ready for review October 24, 2025 17:33
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@VincentLanglet
Copy link
Contributor Author

This issue was more complicated than expected... I'm not against your opinion/review @staabm :)

@VincentLanglet VincentLanglet requested a review from staabm October 29, 2025 21:49
@VincentLanglet VincentLanglet requested a review from staabm October 31, 2025 15:32
@VincentLanglet VincentLanglet force-pushed the isSubClass branch 2 times, most recently from 5aab962 to b37f439 Compare December 5, 2025 15:28
@VincentLanglet
Copy link
Contributor Author

I dunno what to do about the webmozart-assert failure because I don't report anymore

Call to static method Webmozart\Assert\Assert::implementsInterface() with class-string<WebmozartAssertImpossibleCheck\Bar>|WebmozartAssertImpossibleCheck\Bar and 'WebmozartAssertImpossibleCheck\\Bar' will always evaluate to true.

Technically, because a implementsInterface check is called before it's indeed always true.
But strictly looking at the type, calling

class-string<WebmozartAssertImpossibleCheck\Bar>|WebmozartAssertImpossibleCheck\Bar

And currently, phpstan/phpstan-webmozart-assert#194 is showing the issue

@ondrejmirtes
Copy link
Member

@VincentLanglet
Copy link
Contributor Author

This needs to be fixed in phpstan-webmozart-assert before we can merge this: phpstan/phpstan-webmozart-assert@b2221d3/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php#L401-L419

It's been a long time I worked on this PR, but the implementation looks fine to me.
PHPStan will still report most of always-true, always-false implementsInterface calls.

The only issue is the fact it cannot detect

if (\is_subclass_of($object, \stdClass::class, false)) {
      // $object is class-string<\stdClass>|\stdClass
		if (\is_subclass_of($object, \stdClass::class, false)) { // This is not detected as always true
		}
	}

Because I dunno currently a way to say it cannot be the class exactly but only a child or for the call to be remembered.
Maybe you know @staabm ?

And so far I thought it was better to have a missing "always true" report rather than a wrong one.

@staabm
Copy link
Contributor

staabm commented Feb 12, 2026

Because I dunno currently a way to say it cannot be the class exactly but only a child or for the call to be remembered.
Maybe you know @staabm ?

just a guess:

$a->isSuperTypeOf($b)->yes() && $b->isSuperTypeOf($a)->yes() && !$a->equals($b)

or maybe isSubTypeOf()

And so far I thought it was better to have a missing "always true" report rather than a wrong one.

absolutely

@VincentLanglet
Copy link
Contributor Author

Because I dunno currently a way to say it cannot be the class exactly but only a child or for the call to be remembered.
Maybe you know @staabm ?

just a guess:

$a->isSuperTypeOf($b)->yes() && $b->isSuperTypeOf($a)->yes() && !$a->equals($b)

or maybe isSubTypeOf()

It's more with the type instances after

if (\is_subclass_of($object, \stdClass::class, false)) {

how to specify better than class-string<\stdClass>|\stdClass

I feel like we cannot do this without a ChildOfObjectType() or a boolean in ObjectType to require child only and then we specify to class-string<child-of<\stdClass>>|child-of<\stdClass>

So right now @ondrejmirtes, I feel like the best we can is

  • Avoid false error on is_subclass_of where there is uncertainty
  • Lose some "always true" error reported

And a next step could be to introduce a childOnly bool in ObjectType constructor (?)

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.

PHPStan incorrectly narrows type of object after an instanceof check

4 participants