From c8b3dda7c11ab938ffb5d5551d24ea993fbff93e Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 16 Nov 2024 13:45:12 +0100 Subject: [PATCH] Fix ConstantArrayType::isCallable --- src/Type/Constant/ConstantArrayType.php | 14 ++++++- ...mpossibleCheckTypeFunctionCallRuleTest.php | 7 ++++ .../Rules/Comparison/data/bug-12063.php | 38 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Rules/Comparison/data/bug-12063.php diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 76fdf42a5d..53de473e0d 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -481,7 +481,19 @@ public function isCallable(): TrinaryLogic $typeAndMethods, ); - return TrinaryLogic::createYes()->and(...$results); + $isCallable = TrinaryLogic::createYes()->and(...$results); + if ($isCallable->yes()) { + $callableArray = $this->getClassOrObjectAndMethods(); + if ($callableArray !== []) { + [$classOrObject, $methods] = $callableArray; + + if (count($methods->getConstantStrings()) !== count($typeAndMethods)) { + return TrinaryLogic::createMaybe(); + } + } + } + + return $isCallable; } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 5480eb394c..6a5f945522 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -955,4 +955,11 @@ public function testAlwaysTruePregMatch(): void $this->analyse([__DIR__ . '/data/always-true-preg-match.php'], []); } + public function testBug12063(): void + { + $this->checkAlwaysTrueCheckTypeFunctionCall = true; + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-12063.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-12063.php b/tests/PHPStan/Rules/Comparison/data/bug-12063.php new file mode 100644 index 0000000000..0ab9335b84 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-12063.php @@ -0,0 +1,38 @@ += 7.4 + +namespace Bug12063; + +use BadFunctionCallException; + +final class View +{ + public function existingMethod(): void + { + } +} + +final class TwigExtension +{ + private View $viewFunctions; + + public function __construct(View $viewFunctions) + { + $this->viewFunctions = $viewFunctions; + } + + public function iterateFunctions(): void + { + $functionMappings = [ + 'i_exist' => 'existingMethod', + 'i_dont_exist' => 'nonExistingMethod' + ]; + + $functions = []; + foreach ($functionMappings as $nameFrom => $nameTo) { + $callable = [$this->viewFunctions, $nameTo]; + if (!is_callable($callable)) { + throw new BadFunctionCallException("Function $nameTo does not exist in view functions"); + } + } + } +}