Skip to content

Commit 1bf4599

Browse files
VincentLangletphpstan-bot
authored andcommitted
Fix phpstan/phpstan#9844: Static method call on class-string returns mixed instead of ErrorType
- When calling a static method on a non-generic class-string variable, return mixed instead of ErrorType - The fix only applies to class-string types, not to named class or typed object expressions - New regression test in tests/PHPStan/Analyser/nsrt/bug-9844.php - Root cause: class-string converts to ObjectWithoutClassType which has hasMethod() = MAYBE, causing filterTypeWithMethod to bail out and fall back to ErrorType
1 parent 06ea1e1 commit 1bf4599

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

src/Analyser/ExprHandler/StaticCallHandler.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,20 +291,28 @@ public function resolveType(MutatingScope $scope, Expr $expr): Type
291291
return $callType;
292292
}
293293

294+
$calledOnClassString = false;
294295
if ($expr->class instanceof Name) {
295296
$staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($scope, $expr->class, $expr->name);
296297
} else {
297-
$staticMethodCalledOnType = TypeCombinator::removeNull($scope->getType($expr->class))->getObjectTypeOrClassStringObjectType();
298+
$classType = TypeCombinator::removeNull($scope->getType($expr->class));
299+
$calledOnClassString = $classType->isClassString()->yes();
300+
$staticMethodCalledOnType = $classType->getObjectTypeOrClassStringObjectType();
298301
}
299302

303+
$methodName = $expr->name->toString();
300304
$callType = $this->methodCallReturnTypeHelper->methodCallReturnType(
301305
$scope,
302306
$staticMethodCalledOnType,
303-
$expr->name->toString(),
307+
$methodName,
304308
$expr,
305309
);
306310
if ($callType === null) {
307-
$callType = new ErrorType();
311+
if ($calledOnClassString && $staticMethodCalledOnType->hasMethod($methodName)->maybe()) {
312+
$callType = new MixedType();
313+
} else {
314+
$callType = new ErrorType();
315+
}
308316
}
309317

310318
if ($expr->class instanceof Expr) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug9844;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
10+
/**
11+
* @param class-string $class
12+
*/
13+
public function sayHello(string $class): void
14+
{
15+
assertType('mixed', $class::foo());
16+
}
17+
}

0 commit comments

Comments
 (0)