Do not report function_exists/class_exists as always-true conditions#5737
Do not report function_exists/class_exists as always-true conditions#5737phpstan-bot wants to merge 3 commits into
Conversation
staabm
left a comment
There was a problem hiding this comment.
the PR is missing a test for the actual snippet of the bug report
The original reproducer uses function_exists() inside array_filter(), which triggers ImpossibleCheckTypeFunctionCallRule rather than IfConstantConditionRule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. I added a test using the actual reproducer from the bug report — the original snippet uses |
| @@ -0,0 +1,14 @@ | |||
| <?php declare(strict_types = 1); | |||
There was a problem hiding this comment.
merge this file into tests/PHPStan/Rules/Comparison/data/bug-8980.php
There was a problem hiding this comment.
Done. Merged bug-8980-function-call.php into bug-8980.php — the actual bug report snippet (the array_filter + function_exists callback) is now appended to the unified test file, and ImpossibleCheckTypeFunctionCallRuleTest points at the merged file. Tests and PHPStan both pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Closes phpstan/phpstan#8980
After a guard like
if (!function_exists('curl_init')) return;, a subsequentif (function_exists('curl_init'))was reported as "If condition is always true." The same false positive affectedclass_exists().The root cause:
FunctionExistsFunctionTypeSpecifyingExtensionnarrowsfunction_exists('x')totruein the scope after a guard. When a redundant check appears later,ConstantConditionRuleHelper::getBooleanType()evaluates the scope type directly and getsConstantBooleanType(true).The fix adds
function_exists,class_exists,interface_exists,trait_exists, andenum_existsto the skip list inConstantConditionRuleHelper::shouldSkip(), preventing all*ConstantConditionRulevariants from reporting these as constant conditions. Also addsfunction_existsto the exclusion list inImpossibleCheckTypeHelper::findSpecifiedType()alongside the existing entries forclass_exists/interface_exists/trait_exists/enum_exists, preventingImpossibleCheckTypeFunctionCallRulefrom reporting.