Skip to content

Commit c8b3dda

Browse files
Fix ConstantArrayType::isCallable
1 parent de3720d commit c8b3dda

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

src/Type/Constant/ConstantArrayType.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,19 @@ public function isCallable(): TrinaryLogic
481481
$typeAndMethods,
482482
);
483483

484-
return TrinaryLogic::createYes()->and(...$results);
484+
$isCallable = TrinaryLogic::createYes()->and(...$results);
485+
if ($isCallable->yes()) {
486+
$callableArray = $this->getClassOrObjectAndMethods();
487+
if ($callableArray !== []) {
488+
[$classOrObject, $methods] = $callableArray;
489+
490+
if (count($methods->getConstantStrings()) !== count($typeAndMethods)) {
491+
return TrinaryLogic::createMaybe();
492+
}
493+
}
494+
}
495+
496+
return $isCallable;
485497
}
486498

487499
public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,4 +955,11 @@ public function testAlwaysTruePregMatch(): void
955955
$this->analyse([__DIR__ . '/data/always-true-preg-match.php'], []);
956956
}
957957

958+
public function testBug12063(): void
959+
{
960+
$this->checkAlwaysTrueCheckTypeFunctionCall = true;
961+
$this->treatPhpDocTypesAsCertain = true;
962+
$this->analyse([__DIR__ . '/data/bug-12063.php'], []);
963+
}
964+
958965
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types=1); // lint >= 7.4
2+
3+
namespace Bug12063;
4+
5+
use BadFunctionCallException;
6+
7+
final class View
8+
{
9+
public function existingMethod(): void
10+
{
11+
}
12+
}
13+
14+
final class TwigExtension
15+
{
16+
private View $viewFunctions;
17+
18+
public function __construct(View $viewFunctions)
19+
{
20+
$this->viewFunctions = $viewFunctions;
21+
}
22+
23+
public function iterateFunctions(): void
24+
{
25+
$functionMappings = [
26+
'i_exist' => 'existingMethod',
27+
'i_dont_exist' => 'nonExistingMethod'
28+
];
29+
30+
$functions = [];
31+
foreach ($functionMappings as $nameFrom => $nameTo) {
32+
$callable = [$this->viewFunctions, $nameTo];
33+
if (!is_callable($callable)) {
34+
throw new BadFunctionCallException("Function $nameTo does not exist in view functions");
35+
}
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)