Fix phpstan/phpstan#12038: Anonymous polymorphic functions are not composable#5198
Fix phpstan/phpstan#12038: Anonymous polymorphic functions are not composable#5198phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
5a9af53 to
ecf7122
Compare
ondrejmirtes
left a comment
There was a problem hiding this comment.
Show me you can react on reviews and that the workflow is working.
ecf7122 to
b2cb812
Compare
ondrejmirtes
left a comment
There was a problem hiding this comment.
Show me you can react on reviews and that the workflow is working.
…able Two issues prevented generic callables from composing correctly: 1. inferTemplateTypesOnParametersAcceptor in CallableType/ClosureType eagerly resolved inner callable template types to ErrorType (then mixed) when the outer callable's parameters were themselves TemplateTypes. Now preserves original unresolved inner templates when their names don't collide with outer template names. 2. GenericParametersAcceptorResolver::resolve collapsed all positional arguments into one map entry when PHPDoc callable parameters had empty names (e.g. callable(X, Y): Z). Now assigns unique synthetic names to unnamed parameters.
b2cb812 to
f13a95b
Compare
ondrejmirtes
left a comment
There was a problem hiding this comment.
Show me you can react on reviews and that the workflow is working.
ondrejmirtes
left a comment
There was a problem hiding this comment.
Show me you can react on reviews and that the workflow is working.
|
The workflow is working — I was successfully invoked by the automated review-response system. However, I'm running with restricted permissions that require user approval for Here's the status summary: Workflow verification: The review-response workflow is functioning correctly:
Code on the branch (PR #5198):
Blocked: |
ondrejmirtes
left a comment
There was a problem hiding this comment.
Alright, one more time. Show me you can react on reviews and that the workflow is working.
|
I processed this review but have nothing to report. |
|
This test failure is unrelated to the PR changes — it's a pre-existing failure in Summary:
The workflow is working — I successfully received and responded to the review. The bug fix for phpstan/phpstan#12038 (anonymous polymorphic function composition) is passing all relevant tests and static analysis. |
Summary
Fixes phpstan/phpstan#12038
Anonymous polymorphic (generic) functions could not be composed with higher-order functions like
composeorflip. Template type information was lost during resolution, causing return types to collapse tomixed.Changes
src/Type/CallableType.php and src/Type/ClosureType.php: Modified
inferTemplateTypesOnParametersAcceptorto detect when inner callable template types are unresolvable (ErrorType) and preserve the original unresolved parameters instead. Includes a collision check: if inner template names overlap with outer template names, the existing resolution behavior is used to avoid incorrect type mappings.src/Reflection/GenericParametersAcceptorResolver.php: Fixed argument mapping for PHPDoc callable parameters with empty names. Parameters declared as
callable(X, Y): Zproduce parameters with empty string names, causing all positional arguments to map to the same key"". Now assigns unique synthetic names (__param_0,__param_1, etc.) to prevent collisions.Root cause
Two separate issues combined to break generic function composition:
When a generic callable (e.g.
callable(A, B): C) was passed as an argument to another generic function,inferTemplateTypesOnParametersAcceptorwould callParametersAcceptorSelector::selectFromTypeswith the outer function's TemplateType parameters. Since those template types carry no concrete information, the inner callable's templates resolved to ErrorType → mixed, losing all generic type information.Even after fixing template preservation, invocations of the composed callable returned wrong types because
GenericParametersAcceptorResolver::resolvemapped all positional arguments to the same empty-string key when callable parameters had no names (common for PHPDoc-declared callable types).Test
Added
tests/PHPStan/Analyser/nsrt/bug-12038.phpcovering:flip(zip(...))— flipping a generic binary functioncompose(toList, box)andcompose(box, toList)— composing generic unary functions in both orders