Fix #12687: @param-out conditional check does not assign default value#5108
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Open
Fix #12687: @param-out conditional check does not assign default value#5108phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
@param-out conditional check does not assign default value#5108phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
…d variables - When an undefined variable is passed to a by-reference parameter with a default value, use the default value type for resolving conditional @param-out types - In GenericParametersAcceptorResolver::resolve, ErrorType arguments now fall back to the parameter's default value - New regression test in tests/PHPStan/Analyser/nsrt/bug-12687.php Closes phpstan/phpstan#12687
| foreach ($parameters as $param) { | ||
| if (isset($namedArgTypes[$param->getName()])) { | ||
| $argType = $namedArgTypes[$param->getName()]; | ||
| if ($argType instanceof ErrorType && $param->getDefaultValue() !== null) { |
Contributor
There was a problem hiding this comment.
Checking ErrorType seems too permissive.
I wonder if we should introduce custom class extending ErrorType (or some custom data to this class like a reason) and update
phpstan-src/src/Analyser/MutatingScope.php
Line 1439 in bf569e1
Cause something like
$d = $a->getFoo();
assertType('*ERROR*', $d);
Testing::testMethod($d);
assertType('Bug12687\A&Bug12687\I', $d);
seems wrong to me
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
When a
@param-outtype uses a conditional expression that references its own parameter (e.g.,@param-out ($arg is null ? A&I : A) $arg), and an undefined variable is passed to the by-reference parameter, PHPStan was not correctly evaluating the conditional. The undefined variable's type (ErrorType) was used directly to resolve the conditional instead of falling back to the parameter's default value type.Changes
src/Reflection/GenericParametersAcceptorResolver.php: When buildingpassedArgsfor conditional type resolution, if the argument type isErrorType(indicating an undefined variable) and the parameter has a default value, use the default value type insteadtests/PHPStan/Analyser/nsrt/bug-12687.phpRoot cause
In
GenericParametersAcceptorResolver::resolve(), thepassedArgsmap is built from actual argument types. When an undefined variable is passed to a by-reference parameter (likefoo($c)where$cwas never assigned),$scope->getType($c)returnsErrorType. ThisErrorTypewas then used as the subject of the conditional type evaluation ($arg is null ? A&I : A), causing the condition to evaluate incorrectly.The fix checks if the argument type is
ErrorType(undefined variable) and the parameter has a default value, and uses the default value type instead. This mirrors the existing logic for parameters with no argument provided at all (theelseif ($param->getDefaultValue() !== null)branch).Test
Added
tests/PHPStan/Analyser/nsrt/bug-12687.phpwhich verifies that:Aobject resolves the conditional toAnullvariable resolves toA&IA&I(the fix)Fixes phpstan/phpstan#12687