Skip to content

Do not report function_exists/class_exists as always-true conditions#5737

Closed
phpstan-bot wants to merge 3 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-l0l7w4a
Closed

Do not report function_exists/class_exists as always-true conditions#5737
phpstan-bot wants to merge 3 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-l0l7w4a

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Closes phpstan/phpstan#8980

After a guard like if (!function_exists('curl_init')) return;, a subsequent if (function_exists('curl_init')) was reported as "If condition is always true." The same false positive affected class_exists().

The root cause: FunctionExistsFunctionTypeSpecifyingExtension narrows function_exists('x') to true in the scope after a guard. When a redundant check appears later, ConstantConditionRuleHelper::getBooleanType() evaluates the scope type directly and gets ConstantBooleanType(true).

The fix adds function_exists, class_exists, interface_exists, trait_exists, and enum_exists to the skip list in ConstantConditionRuleHelper::shouldSkip(), preventing all *ConstantConditionRule variants from reporting these as constant conditions. Also adds function_exists to the exclusion list in ImpossibleCheckTypeHelper::findSpecifiedType() alongside the existing entries for class_exists/interface_exists/trait_exists/enum_exists, preventing ImpossibleCheckTypeFunctionCallRule from reporting.

Copy link
Copy Markdown
Contributor

@staabm staabm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the PR is missing a test for the actual snippet of the bug report

https://phpstan.org/r/8a878842-90c2-42ff-aee3-7fa290df7cd4

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>
@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

Done. I added a test using the actual reproducer from the bug report — the original snippet uses function_exists() inside array_filter(), which triggers ImpossibleCheckTypeFunctionCallRule (not IfConstantConditionRule). The test verifies no false positive is reported. Both make tests and make phpstan pass.

@@ -0,0 +1,14 @@
<?php declare(strict_types = 1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge this file into tests/PHPStan/Rules/Comparison/data/bug-8980.php

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@staabm staabm closed this May 23, 2026
@staabm staabm deleted the create-pull-request/patch-l0l7w4a branch May 23, 2026 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants