Fix phpstan/phpstan#11619: Parameter #2 $callback of function uasort expects callable(Foo, Foo): int, 'strnatcasecmp' given.#5171
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
…mode - Propagated $strictTypes from CallableType::accepts() through to CallableTypeHelper - In non-strict mode, Stringable objects are now accepted where string is expected in callable parameters - This fixes false positives for patterns like uasort($stringableArray, 'strnatcasecmp') - In strict_types mode, the stricter behavior is preserved (e.g. closures with explicit string params) - New regression test in tests/PHPStan/Rules/Functions/data/bug-11619.php Closes phpstan/phpstan#11619
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PHPStan incorrectly reported an error when passing a string-comparison function like
strnatcasecmptouasort()for arrays ofStringableobjects. For example,uasort($options, 'strnatcasecmp')where$optionsisFoo[]andFooimplementsStringablewould produce: "Parameter #2 $callback of function uasort expects callable(Foo, Foo): int, 'strnatcasecmp' given."This is a false positive because PHP's internal functions like
strnatcasecmpperform implicit type coercion fromStringabletostring.Changes
src/Type/CallableType.php: Propagated the$strictTypesparameter fromaccepts()throughisSuperTypeOfInternal()toCallableTypeHelper::isParametersAcceptorSuperTypeOf()src/Type/CallableTypeHelper.php: Added optional$strictTypesparameter (defaulttrue) and used it in the callable parameter acceptance check instead of the hardcodedtruetests/PHPStan/Rules/Functions/data/bug-11619.php: New regression test withStringableclass anduasort/usortwithstrnatcasecmptests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php: AddedtestBug11619test methodRoot cause
CallableType::accepts()received a$strictTypesparameter but ignored it, always passingtreatMixedAsAny=trueto its internal method without forwarding$strictTypes. TheCallableTypeHelper::isParametersAcceptorSuperTypeOf()hardcodedstrictTypes=truewhen calling$theirParameter->getType()->accepts(), which causedStringType::accepts()to rejectStringableobjects without checking for__toString().The fix propagates the scope's
$strictTypesvalue through the chain. In non-strict mode (nodeclare(strict_types=1)),StringType::accepts()now checks for__toString()and acceptsStringableobjects. In strict mode, the existing behavior is preserved, which correctly handles cases like bug-12317 where a user-defined closure with explicitstringparameter types should still be flagged.Test
Added
tests/PHPStan/Rules/Functions/data/bug-11619.phpwith aStringableclassFooand calls touasort($options, 'strnatcasecmp')andusort($options, 'strnatcasecmp'). The test expects no errors.Fixes phpstan/phpstan#11619