Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix param castable to string rule #3141

Merged
merged 10 commits into from
Jun 17, 2024

Conversation

schlndh
Copy link
Contributor

@schlndh schlndh commented Jun 10, 2024

Fixes phpstan/phpstan#11167, but for some reason the issue is not reported as changed by the Issue Bot action. 🤔

Comment on lines 135 to 140
if ($flags === null || $flags->equals(new ConstantIntegerType(SORT_REGULAR))) {
return [];
}

foreach (TypeUtils::getConstantIntegers($flags) as $flag) {
if ($flag->getValue() !== SORT_NUMERIC) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure what's the best way to handle flags like this. My thinking is as follows:

  • SORT_REGULAR does not have any constraints, so I only check for equality. If there is a union (or int), then the stricter check should be maintained.
  • SORT_NUMERIC seems the strictest (though not exactly, because it does allow arrays, unlike SORT_STRING), so if it's a union SORT_NUMERIC and something else, I go with SORT_NUMERIC.
  • Otherwise, I assume SORT_STRING (or SORT_LOCALE_STRING which is the same for our purposes).

The only edge-case that I can think of right now is e.g. array_unique([[1], [2]], rand() ? SORT_NUMERIC : SORT_STRING). IDK if it's worth it to complicate it further with such edge cases. 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Upon further consideration I changed it. My thinking is that it should enforce the strongest constraint which it cannot prove to be unnecessary. So sort($arr, $int) and sort($arr, rand() ? SORT_STRING : SORT_NUMERIC) will require castability to both string and float. So the previously mentioned edge-case is now prohibited as well.

I found one more edge-case: statically known invalid flag (e.g. sort($arr, 128)). Based on my testing it seems to fall back to SORT_REGULAR in that case (I included array_unique because it has a different default value - I was thinking that it may fall back to the default value). I allowed this case (it should be prohibited, just not by this rule).

@ondrejmirtes
Copy link
Member

An idea: instead of these huge if-else, let's split this rule in multiple ones focused on each family of functions.

@schlndh
Copy link
Contributor Author

schlndh commented Jun 10, 2024

I'll try that on Wednesday, I need a bit of a break. 😅

@schlndh schlndh force-pushed the fix-paramCastableToStringRule branch from ad439fd to 3ec4699 Compare June 12, 2024 14:46
Comment on lines 61 to 62
!in_array($functionName, $checkAllArgsFunctions, true)
&& !in_array($functionName, $checkFirstArgFunctions, true)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I kept these two groups together, since the only difference is which parameters are checked.

$flags = $functionParameters[1]->getDefaultValue();
}

if ($flags === null || $flags->equals(new ConstantIntegerType(SORT_REGULAR))) {
Copy link
Contributor

@staabm staabm Jun 12, 2024

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All other valid flags are stricter, so IMO it's not necessary to support union types in this condition.

@ondrejmirtes
Copy link
Member

for some reason the issue is not reported as changed by the Issue Bot action

Because the issue is not yet tagged as bug / feature request.


$errors = [];

foreach ($argsToCheck as $argIdx => $arg) {
Copy link
Member

Choose a reason for hiding this comment

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

The duplicated part of the rules should be moved to a common "Something...Check" class.

@ondrejmirtes ondrejmirtes merged commit 322de33 into phpstan:1.11.x Jun 17, 2024
446 of 449 checks passed
@ondrejmirtes
Copy link
Member

Perfect, thank you!

@schlndh schlndh deleted the fix-paramCastableToStringRule branch June 17, 2024 15:17
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.

array_unique($array, SORT_REGULAR) works even for non-stringable values, but is reported
3 participants