Il y a quelques années, j'ai pris une décision dont j'avais un peu honte : j'ai sorti notre job Psalm du hook pre-commit pour le laisser uniquement en CI, parce que personne dans l'équipe ne supportait d'attendre 50 secondes à chaque correction de faute de frappe. J'avais l'impression de baisser le niveau d'exigence. Puis j'ai vu la même chose se produire dans trois autres équipes, et j'ai arrêté de culpabiliser : l'outil et la façon de travailler n'allaient tout simplement pas ensemble. C'est précisément cette démangeaison que Jorg Sowa dit avoir voulu soulager en lançant mir en avril 2026, et les chiffres qu'il a publiés sont difficiles à ignorer.
Quelques faits, parce qu'ils comptent. mir est écrit en Rust, sous licence MIT, et en est à la version 0.88. Sur un même portable, il analyse Symfony et Laravel en 0.7 à 2 secondes ; Psalm mettait 37 à 54 secondes, avec un pic de 3 à 4 GB de mémoire entre son processus principal et ses neuf workers. Sowa annonce un gain de 19 à 82 fois plus rapide pour un cinquième de la mémoire, voire moins. Le test sur Symfony a utilisé le commit b47221ac avec le psalm.xml d'origine de Symfony, sans retouche, au niveau d'erreur 5 et avec sa baseline ; celui sur Laravel couvrait les 1,742 fichiers de la v13.36.0. Il reconnaît honnêtement que le mode --diff de Psalm, qui ne revérifie que les fichiers modifiés, ne faisait pas partie de la comparaison, et j'aimerais bien voir cette colonne remplie avant que quiconque prenne le 82x pour parole d'évangile.
Mais ce qui me trotte dans la tête, ce n'est pas le chrono. mir n'apporte pas son propre langage de types. Il lit psalm.xml quand il n'y a pas de mir.xml, récupère tout seul psalm-baseline.xml, respecte les errorLevel de 1 à 8 avec la correspondance par type d'erreur de Psalm, et accepte @psalm-pure, @psalm-immutable, @psalm-suppress et compagnie, ainsi que la syntaxe PHPStan et @phpstan-ignore. Les noms d'erreurs comme InvalidArgument et TaintedSql restent identiques quand les deux outils ont la même vérification. Autrement dit, ce qui a commencé chez Vimeo comme le dialecte de docblocks d'un seul projet est devenu une interface qu'un moteur complètement indépendant peut implémenter. C'est un sacré compliment pour la communauté PHP. On a construit, dans des commentaires, un système de types plus riche que celui du langage lui-même, et il s'est révélé assez solide pour survivre à n'importe laquelle de ses implémentations.
Et c'est justement pour ça que l'étape suivante me paraît aussi ennuyeuse qu'indispensable : il nous faut une spécification écrite du langage de types des docblocks. Aujourd'hui, ce que veulent dire list<T>, non-empty-string ou un array shape avec des types littéraux dans un cas limite, c'est ce que Psalm en fait, avec l'accord global de PHPStan et, depuis PhpStorm 2020.3, une compréhension approximative de ton IDE. Avec un troisième interpréteur sérieux dans la partie, « ce que fait Psalm » ne suffit plus. Sowa lui-même prévient que ton premier lancement de mir produira une liste d'erreurs différente, que toutes les règles n'existent pas encore et que certains noms changent. Une partie de ces écarts, c'est juste du travail pas encore fini. Une autre partie, ce seront de vrais désaccords sur le sens d'un type, et sans spec, personne ne pourra dire qui a raison.
L'objection la plus sérieuse à tout cet enthousiasme, je la prends au mot. Psalm est écrit en PHP, ce qui veut dire que ceux qui l'utilisent peuvent le lire, le déboguer et envoyer un patch un dimanche après-midi. Un analyseur en Rust met le moteur hors de portée de la plupart de ses utilisateurs. Les plugins illustrent bien le prix à payer : mir propose une API de plugins native en Rust inspirée des event handlers de Psalm, et les plugins PHP existants, comme celui pour PHPUnit, ne fonctionnent qu'à travers un pont qui lance un sous-processus PHP, ce qui exige toujours d'avoir PHP et Psalm installés. Si l'outillage d'analyse de la communauté glisse vers un cercle plus restreint de mainteneurs dans un autre langage, on perd vraiment en résilience, et je ne vais pas faire semblant du contraire.
Malgré tout, je penche pour l'accueillir à bras ouverts, pour une raison pratique. Ton investissement n'a jamais été dans le code source de Psalm. Il est dans les annotations que ton équipe a écrites pendant des années, dans la baseline que tu grignotes petit à petit, dans les suppressions accompagnées d'un commentaire qui explique pourquoi. Comme mir traite tout ça comme le contrat, l'essayer te coûte un composer require et une commande, et tu peux faire tourner les deux analyseurs côte à côte en CI jusqu'à ce que tu fasses confiance aux résultats. Rien n'est à réécrire. Si mir reste bloqué en 0.9 pour toujours, tu le désinstalles et tu as perdu un après-midi. Les développeurs Go ont eu leurs linters rapides en réécrivant les outils et en demandant à tout le monde d'adopter de nouvelles conventions ; nous, on garde les nôtres et on change le moteur en dessous, ce qui est franchement un meilleur deal.
Ce qui change quand l'analyse prend deux secondes, c'est le moment où tu la lances. À 50 secondes, c'est une barrière que tu franchis une fois avant de pousser. À moins de deux, elle peut tourner à chaque sauvegarde, et les erreurs de types apparaissent pendant que tu te souviens encore de pourquoi tu as écrit la ligne. Ce changement d'habitude vaut plus que n'importe quel graphique de benchmark, et c'est justement ce que la conception de Psalm n'a jamais pu complètement nous offrir, aussi bonne que soit son analyse. J'échangerais volontiers quelques règles manquantes contre ça, au moins sur une branche de fonctionnalité.
Alors je suis curieux de savoir où tu te situes, surtout si tu maintiens une bibliothèque qui publie des types précis dans ses docblocks. Si deux moteurs ne sont pas d'accord sur une de tes signatures @template, lequel considères-tu comme fautif, et est-ce que tu mettrais ton nom derrière une spec maintenue par la communauté pour ce langage de types, ou est-ce que tu penses que laisser les outils converger d'eux-mêmes est la voie la plus saine ?




Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.