Skip to content

Fix phpstan/phpstan#2572: Optional templated args not provided cause unbound template errors#5175

Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-h8wtlni
Open

Fix phpstan/phpstan#2572: Optional templated args not provided cause unbound template errors#5175
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-h8wtlni

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When a function has a template type bound to a variadic parameter (e.g. @param TR ...$elts) and the function is called without providing any variadic arguments, PHPStan incorrectly reports "Unable to resolve the template type TR". Since variadic parameters are optional, not providing them should not trigger this error.

Changes

  • Modified src/Reflection/GenericParametersAcceptorResolver.php to infer NeverType for variadic parameters that receive no arguments, instead of leaving the template type as ErrorType
  • Added rule regression test in tests/PHPStan/Rules/Functions/data/bug-2572.php and tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php
  • Added type inference test in tests/PHPStan/Analyser/nsrt/bug-2572.php

Root cause

In GenericParametersAcceptorResolver::resolve(), all template types are initially mapped to ErrorType, then overwritten by types inferred from actual arguments. When a variadic parameter receives no arguments, it was simply skipped (continue), leaving its template type as ErrorType. The FunctionCallParametersCheck then saw this ErrorType and reported the template as unresolvable.

The fix adds an elseif ($param->isVariadic()) branch that infers the template type from NeverType instead of skipping. This is semantically correct: an empty variadic parameter means an empty array, and the element type of an empty array is never. This causes TE|TR to resolve to TE|never = TE, which is the expected behavior.

Test

  • Rule test verifies no errors are reported for collect("a") (previously a false positive) and collect("a", "b", "c") (always worked)
  • NSRT test verifies collect("a") infers type 'a' and collect("a", "b", "c") infers type 'a'|'b'|'c'

Fixes phpstan/phpstan#2572

…rams

- When a template type is only used on a variadic parameter and no arguments are passed, it was incorrectly reported as unresolvable
- Fixed by inferring NeverType for variadic parameters with no arguments in GenericParametersAcceptorResolver, since an empty variadic means the element type is never
- Added regression tests in both rule test and NSRT format

Closes phpstan/phpstan#2572
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.

1 participant