Skip to content

Fix #13904: narrow scope on version_compare( PHP_VERSION, '8.4', '<' )#4950

Open
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-qaxm90y
Open

Fix #13904: narrow scope on version_compare( PHP_VERSION, '8.4', '<' )#4950
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-qaxm90y

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Closes phpstan/phpstan#13904

This PR adds PHP version scope narrowing when version_compare() is used with PHP_VERSION in conditions:

  • Three-argument form: version_compare(PHP_VERSION, '8.4', '<') now narrows PHP_VERSION_ID in both the truthy and falsey branches, supporting all operators (<, <=, >, >=, ==, != and their aliases lt, le, gt, ge, eq, ne)
  • Two-argument form: version_compare(PHP_VERSION, '8.0') === 1, version_compare(PHP_VERSION, '8.0') < 0, etc. narrow PHP_VERSION_ID based on the comparison result
  • Swapped arguments: version_compare('8.0', PHP_VERSION, '<') is handled by reversing the comparison direction
  • Patch versions: version_compare(PHP_VERSION, '8.4.1', '>=') correctly narrows to int<80401, max>

Implementation

  • New VersionCompareFunctionTypeSpecifyingExtension handles the three-argument form by converting the version string to a PHP_VERSION_ID integer and building a synthetic comparison expression that is processed by the existing TypeSpecifier narrowing logic
  • Two-argument form handling is added directly in TypeSpecifier (in both the Smaller/SmallerOrEqual section and resolveNormalizedIdentical) by mapping the comparison result set to PHP_VERSION_ID type constraints

Test plan

  • New test file tests/PHPStan/Analyser/nsrt/version-compare-scope-narrowing.php covers all forms
  • Existing version-compare-php8.php test continues to pass
  • Full test suite passes (13856 tests)
  • PHPStan self-analysis passes with no errors
  • Coding standards check passes

staabm and others added 2 commits February 16, 2026 09:28
When version_compare(PHP_VERSION, '8.4', '<') or similar calls are
used in conditions, PHPStan now narrows the PHP_VERSION_ID type in
the corresponding scope branches, matching the existing behavior of
direct PHP_VERSION_ID comparisons.

Supports all three-argument operators (<, <=, >, >=, lt, le, gt, ge,
==, =, eq, !=, <>, ne), the two-argument form compared with ===, !==,
<, <=, >=, >, and PHP_VERSION in either argument position.

Closes phpstan/phpstan#13904
Closes phpstan/phpstan#13904

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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