Skip to content

Fix #9844: Calling a static method over non-generic class-string results in ErrorType#4964

Open
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-nv89o4p
Open

Fix #9844: Calling a static method over non-generic class-string results in ErrorType#4964
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-nv89o4p

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Calling a static method on a non-generic class-string (e.g., $class::foo() where $class is typed as class-string) resulted in ErrorType instead of MixedType. This also affected static method calls on mixed values.

Changes

  • Modified src/Analyser/MutatingScope.php (getStaticCallType method): Added a check so that when methodCallReturnType() returns null for a static call on an expression, and the resolved type has no known class names (i.e., it's something like ObjectWithoutClassType) and hasMethod() is not definitively no, the result is MixedType instead of ErrorType.
  • Added regression test tests/PHPStan/Analyser/nsrt/bug-9844.php

Root cause

When a static method is called on a class-string variable, the type goes through getObjectTypeOrClassStringObjectType() which converts it to ObjectWithoutClassType. This type returns TrinaryLogic::createMaybe() for hasMethod(), meaning the method might exist but we don't know. However, filterTypeWithMethod() only accepts types where hasMethod() returns yes, so it rejects ObjectWithoutClassType and returns null. The calling code then fell back to ErrorType.

The fix distinguishes between:

  1. Unknown class types (from class-string or mixed): ObjectWithoutClassType with no class names → return MixedType since any method could exist
  2. Known class types accessed via variable (e.g., $foo::method() where $foo: SomeClass): These have known class names even though hasMethod() may return maybe for non-final classes → correctly return ErrorType when the method doesn't exist

Test

Added tests/PHPStan/Analyser/nsrt/bug-9844.php which tests that $class::foo() where $class is class-string returns mixed instead of *ERROR*.

Fixes phpstan/phpstan#9844

phpstan-bot and others added 2 commits February 16, 2026 23:40
- When calling a static method on a non-generic class-string (e.g. $class::foo()
  where $class is class-string), the result was ErrorType instead of MixedType
- Root cause: class-string converts to ObjectWithoutClassType via
  getObjectTypeOrClassStringObjectType(), which returns maybe for hasMethod(),
  causing filterTypeWithMethod() to reject it and methodCallReturnType() to
  return null, falling back to ErrorType
- Fix checks if the static call is on an expression (not a class name), the
  resolved type has no known class names, and hasMethod is not definitively no,
  returning MixedType in that case
- New regression test in tests/PHPStan/Analyser/nsrt/bug-9844.php

Closes phpstan/phpstan#9844
Automated fix attempt 1 for CI failures.
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.

1 participant