Quem depende do PHPStan em pipelines de CI/CD costuma sentir cada minuto gasto em análise estática, principalmente em monorepos e bases grandes. A versão PHPStan 2.1.34 chega com um pacote agressivo de otimizações que promete reduzir o tempo total de execução em 25-40%, além de uma novidade técnica importante: uso de Fibers em PHP 8.1+ para aumentar a precisão da inferência de tipos em chamadas específicas.
Destaques
- 25-40% de ganho de performance em projetos típicos, com foco no hot path do analisador.
- Cache de objetos de reflection e PHPDocs resolvidos, além de dezenas de micro-otimizações no core.
- Uso de Fibers em PHP 8.1+ para inferência mais precisa em chamadas como
doFoo($a = 1, $a). - Correções críticas para evitar crash em
curl_setopte melhorias emrange()ecount()para tipos mais exatos.
O salto de performance que deve aparecer no seu CI
O headline desta release é simples: menos tempo esperando o job terminar. O ganho anunciado de 25-40% vem de uma combinação de mudanças estruturais e “micro-ajustes” que atacam o custo acumulado de operações repetidas ao longo da análise.
O changelog destaca dois pilares:
- Caching de objetos de reflection e PHPDocs resolvidos, reduzindo trabalho redundante ao navegar por classes, métodos e docblocks.
- Uma sequência de otimizações no código do analisador, com foco em evitar merges e cálculos desnecessários, reduzir IO repetitivo, diminuir loops e minimizar transformações de tipos custosas.
Aqui vale crédito direto: boa parte desse refinamento aparece associada ao trabalho do @staabm, que assina uma quantidade grande de PRs ligados ao desempenho. Na prática, isso tende a impactar mais quem roda o PHPStan com frequência, em PRs e branches, onde cada melhoria de alguns milissegundos por nó vira minutos poupados no final.
Exemplos do tipo de otimização aplicada
Sem entrar em cada PR, o padrão do que foi feito é bem claro:
- Menos leitura e parsing repetidos (por exemplo, evitar ler e decodificar
composer.jsonmais de uma vez, cache de leituras de arquivos.neon). - Menos trabalho durante combinação e travessia de tipos (redução de chamadas repetidas de operações como intersect/union, atalhos de “cheap checks first”).
- Menos custo em loops muito quentes do
NodeScopeResolver,MutatingScope,TypeSpecifiere afins.
Resultado esperado: análise mais rápida sem mexer em regra nenhuma do seu lado.
Deep dive: como Fibers deixam a inferência mais precisa
A grande inovação técnica desta release é usar Fibers (recurso do PHP 8.1+) para resolver um problema clássico de “tempo” na análise: quando uma regra tenta ler o tipo de um argumento, mas o estado do $scope ainda não reflete a resolução daquele trecho do AST.
O exemplo citado no release é este:
doFoo($a = 1, $a);O problema sem Fibers
Imagine uma regra engatada no nó MethodCall (ou algo equivalente) que, durante o processamento, faz:
$scope->getType($node->args[1])
Sem Fibers, em certos cenários o $scope “enxerga” o estado anterior à chamada. Ou seja, quando a regra tenta obter o tipo do segundo argumento ($a), a atribuição do primeiro argumento ($a = 1) ainda não foi considerada para aquele ponto do fluxo. O resultado costuma cair em mixed, porque, naquele instante, o analisador ainda não consolidou a informação necessária.
O que muda com Fibers
Com Fibers, o PHPStan consegue modelar essa dependência temporal de forma mais fiel:
- A regra pede o tipo do segundo argumento cedo demais.
- O analisador pausa a execução da regra, porque sabe que o tipo ainda será resolvido com precisão.
- Quando o processamento chega efetivamente ao segundo argumento, o estado já está atualizado.
- A execução da regra é retomada, e então
$scope->getType($node->args[1])passa a ver o tipo correto, que neste caso é1(em vez demixed).
Isso é especialmente relevante para regras e extensões que dependem de inferência fina em argumentos sequenciais, onde o “antes e depois” no mesmo nó faz diferença real. O projeto indica que essa mudança resolve 10 issues reportadas, o que sugere que não é um ajuste teórico, e sim algo que já estava doendo em projetos reais.
ANÁLISE TÉCNICA: ferramentas de análise estática estão ficando mais “inteligentes” não só por adicionar regras, mas por usar recursos modernos da linguagem para representar melhor a execução e o fluxo de informações. O uso de Fibers aqui é um bom sinal de maturidade: em vez de aceitar mixed como destino final, o analisador passa a lidar com dependências de tempo de forma explícita, melhorando precisão sem exigir workarounds do desenvolvedor.
Correções importantes que evitam dor de cabeça
Além de performance e Fibers, a versão traz correções e melhorias de tipos que aparecem muito no dia a dia:
curl_setopt: correção para evitar crash durante a análise, um tipo de falha que interrompe pipeline e costuma ser caro de diagnosticar.range(): retorno melhorado para indicar que a função sempre produz uma non-empty-list, ajudando regras e checagens que se beneficiam de coleções não vazias.count()comCOUNT_RECURSIVE: o tipo de retorno foi refinado paraint<1, max>quando aplicado a non-empty-array, reduzindo falsos positivos e melhorando validações.
Há também correções em áreas como tipos de união/reflection, operadores bitwise em mixed e normalização de argumentos, que, somadas, tendem a reduzir ruído e inconsistências ao longo do uso.
Conclusão
A PHPStan 2.1.34 é uma release com duas mensagens fortes: menos tempo de execução, e inferência de tipos mais precisa em cenários onde o estado do fluxo importa. Se você roda análise estática em projetos grandes, vale testar, medir e comparar, especialmente em jobs de CI, onde o ganho de 25-40% pode virar uma economia bem concreta ao longo do mês. O próprio projeto incentiva: rode na sua base e reporte seus números.
