Skip to content

[2.1.35 regression] Closure parameter types no longer inferred from expected Closure signature #13993

@gnutix

Description

@gnutix

Bug report

In 2.1.35, closure parameter types are no longer inferred from the expected Closure type signature when passed to a function. This causes cascading type inference failures, particularly with array destructuring and generator key types.

This broke 47 usages in our codebase that rely on this inference pattern, particularly with collectWithKeys-style functions that accept callable(T): iterable<K, V> like this :

/**
 * @template K of array-key
 * @template T
 * @template L of array-key
 * @template U
 *
 * @param array<K, T> $array
 * @param callable(T, K): iterable<L, U> $fn
 *
 * @return array<L, U>
 */
function collectWithKeys(array $array, callable $fn): array;

Code snippet that reproduces the problem

https://phpstan.org/r/c3f59f57-92a2-4db9-9a5d-e87d3334c0fa

Expected output

PHPStan should infer the closure parameter type from the expected Closure signature:

  • $input should be array<array{int, string}>
  • $id should be int (from destructuring)
  • $name should be string (from destructuring)
  • Generator key should be int

Did PHPStan help you today? Did it make you happy in any way?

The 2.1.34 upgrade brought significant performance improvements in our CI pipeline analysis! Thank you for your ongoing work on this beloved library! ❤️

Code stack Nb lines of code Before After Improvement
Symfony/CQRS 366'008 ~7m 30s ~5m 05s 32% faster
Legacy 183'265 ~4m 30s ~3m 00s 33% faster
Total 549'273 ~12m ~8m ~33% faster

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions