Skip to content

Commit c38813d

Browse files
phpstan-botclaude
andcommitted
Report staticMethod.notFound error for static calls on class-string
Static method calls on bare class-string (e.g. $class::foo()) now report "Call to an undefined static method class-string::foo()" instead of silently returning no errors. This is consistent with how object type static calls already report the error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 855a825 commit c38813d

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

src/Rules/Methods/StaticMethodCallCheck.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424
use PHPStan\Rules\RuleLevelHelper;
2525
use PHPStan\ShouldNotHappenException;
2626
use PHPStan\TrinaryLogic;
27+
use PHPStan\Type\ClassStringType;
2728
use PHPStan\Type\ErrorType;
2829
use PHPStan\Type\Generic\GenericClassStringType;
30+
use PHPStan\Type\ObjectWithoutClassType;
2931
use PHPStan\Type\StaticType;
3032
use PHPStan\Type\StringType;
3133
use PHPStan\Type\Type;
@@ -200,11 +202,14 @@ public function check(
200202
if (!$classType->isObject()->yes()) {
201203
return [[], null];
202204
}
205+
} elseif ($classType instanceof ClassStringType) { // @phpstan-ignore phpstanApi.instanceofType
206+
$typeForDescribe = $classType;
207+
$classType = new ObjectWithoutClassType();
203208
} elseif ($classType->isString()->yes()) {
204209
return [[], null];
205210
}
206211

207-
$typeForDescribe = $classType;
212+
$typeForDescribe ??= $classType;
208213
if ($classType instanceof StaticType) {
209214
$typeForDescribe = $classType->getStaticObjectType();
210215
}

tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ public function testCallStaticMethods(): void
243243
'Static call to instance method CallStaticMethods\InterfaceWithStaticMethod::doInstanceFoo().',
244244
213,
245245
],
246+
[
247+
'Call to an undefined static method class-string::nonexistentMethod().',
248+
295,
249+
],
246250
[
247251
'Static method CallStaticMethods\Foo::test() invoked with 3 parameters, 0 required.',
248252
298,
@@ -1009,4 +1013,21 @@ public function testPipeOperator(): void
10091013
]);
10101014
}
10111015

1016+
public function testBug9844(): void
1017+
{
1018+
$this->checkThisOnly = false;
1019+
$this->checkExplicitMixed = false;
1020+
$this->checkImplicitMixed = false;
1021+
$this->analyse([__DIR__ . '/data/bug-9844.php'], [
1022+
[
1023+
'Call to an undefined static method class-string::foo().',
1024+
13,
1025+
],
1026+
[
1027+
'Call to an undefined static method object::foo().',
1028+
21,
1029+
],
1030+
]);
1031+
}
1032+
10121033
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug9844;
4+
5+
class HelloWorld
6+
{
7+
8+
/**
9+
* @param class-string $class
10+
*/
11+
public function sayHello(string $class): void
12+
{
13+
$class::foo();
14+
}
15+
16+
/**
17+
* @param object $class
18+
*/
19+
public function sayHello2(object $class): void
20+
{
21+
$class::foo();
22+
}
23+
}

0 commit comments

Comments
 (0)