Skip to content

Fix phpstan/phpstan#13092: Using result of random_int in another random_int results in an error#5411

Closed
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-iv7kb74
Closed

Fix phpstan/phpstan#13092: Using result of random_int in another random_int results in an error#5411
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-iv7kb74

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When using the result of random_int() in another random_int() call (e.g. random_int($shoppers, $shoppers * 3)), PHPStan incorrectly reported that $min expects a lower number than $max. This is a false positive because the ranges are correlated through the shared variable - if $shoppers is 1000 then max is 3000, if $shoppers is 10000 then max is 30000, so max is always >= min.

Changes

  • Modified src/Rules/Functions/RandomIntParametersRule.php to skip reporting "maybe" errors when both arguments share a variable reference
  • Added sharesVariable() and extractVariableNames() helper methods that recursively extract variable names from argument expressions and check for overlap
  • Added regression test in tests/PHPStan/Rules/Functions/data/bug-13092.php

Root cause

The RandomIntParametersRule checks if $max < $min is possible. With $shoppers as int<1000, 10000> and $shoppers * 3 as int<3000, 30000>, the ranges overlap (min could be 10000, max could be 3000), so isSmallerThan returns "maybe". With strict rules enabled (reportMaybes=true), this was reported as an error. However, since both arguments are derived from the same variable, the ranges are correlated and max can never actually be less than min. The fix detects shared variables between the two argument expressions and suppresses "maybe" reports in that case.

Test

Added tests/PHPStan/Rules/Functions/data/bug-13092.php which reproduces the exact scenario from the issue: $shoppers = random_int(1000, 10000); $transactions = random_int($shoppers, $shoppers * 3); - expects no errors.

Fixes phpstan/phpstan#13092

…args

- Skip reporting "maybe" errors in RandomIntParametersRule when both arguments share a variable reference
- When $min and $max are derived from the same variable (e.g. random_int($x, $x * 3)), the ranges are correlated and max can never be less than min
- Added sharesVariable/extractVariableNames helper methods to detect shared variables in argument expressions
- New regression test in tests/PHPStan/Rules/Functions/data/bug-13092.php
Copy link
Copy Markdown
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

I don't like this this because it won't report anymore

\random_int($shoppers, $shoppers - 1);

…anket suppression

Instead of suppressing all "maybe" errors when arguments share a variable,
evaluate both expressions at the boundary values of shared variables and only
suppress when max >= min for all combinations. This ensures cases like
random_int($x, $x - 1) are still reported as errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

Both background tasks confirmed complete — make tests also passed (11736 tests, 78977 assertions). All done.

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