Annonce de Psalm 5

November 30, 2022 by The Maintainers of Psalm - 4 minute read

Lire cet article en Anglais, Italien ou en Ukrainien


On aimerait tous pouvoir remonter le temps, que ce soit pour corriger une erreur du passé, dire à un être aimé ce qu'il représente pour nous ou pour corriger une petite erreur dans un outil d'analyse statique pour PHP.

Malheureusement, les machines à remonter le temps n'existent pas, mais les versions logicielles majeures existent. Le changement le plus visible pour les utilisateurs de Psalm 5 est une correction relativement mineure: les tableaux clés/valeurs sont désormais scellés par défaut.

Tableaux clés/valeurs scellés vs descellés

Si vous avez déjà utilisé les tableaux clés/valeurs, vous devriez reconnaitre cette syntaxe:

<?php

/**
 * @param array{id: string, name: string} $user
 * @return array{id: string, name: string}
 */
function takesUserData(array $user): array {
  return $user;
}

Dans l'exemple précédent, takesUserData n'accepte qu'un tableau avec exactement deux éléments: id et name. Le bloc de documentation de cette fonction nous dit qu'elle retourne un tableau, également avec exactement deux éléments.

Psalm accepte également un array{id: string, name: string} pour une function qui attend un array<string>. C'est assez cohérent — le tableau contient seulement des éléments de type string, donc on doit pouvoir les passer à une fonction (comme implode) qui attend un tableau de string.

Qu'arrive t'il si on change notre fonction pour ajouter un autre élément dans le corps de la fonction takesUserData?

<?php

/**
 * @param array{id: string, name: string} $user
 * @return array{id: string, name: string}
 */
function takesUserData(array $user): array {
  $user['extra_data'] = new stdClass();
  return $user;
}

Psalm se plaint désormais que l'on ne retourne pas ce que l'on avait prévu - c'est un changement par rapport aux versions précédentes qui autorisaient ce comportement.

Le précédent comportement (erroné) signifie que l'on pouvait faire quelque chose comme implode('', takesUserData($foo)) sans que Psalm ne remonte d'erreur. Cela pouvait aboutir à un code qui plante à l'exécution.

Quand un outil d'analyse statique autorise des comportements qui aboutissent à des erreurs à l'exécution, on ne peut pas dire de cet outil qu'il respecte la sûreté du typage. Il y a quelques cas particuliers en PHP pour lesquels on ne peut pas garantir la sûreté, mais Psalm essaye de les éviter quand c’est possible. Nous avons décidé de légèrement changer le comportement de Psalm de façon à ce qu'il cause un minimum d'inconvénients pour ses utilisateurs.

Un mot de Matt Brown, le créateur de Psalm:

C'est entièrement ma faute. Désolé. J'ai inventé la syntaxe array{id: string, name: string} mais je n'ai pas suffisamment fouillé la sémantique.

Au moment de l’écriture de cet article, les autres outils d'analyse statique (Phan , PHPStan) autorisent ce comportement, et nous espérons qu'avec le temps, ils adopteront également la syntaxe ... pour garantir la sûreté du typage des tableaux clés/valeurs

Si vous souhaitez avoir une fonction qui autorise plus de clés que celles explicitées, vous pouvez utiliser ... pour documenter que le tableau est descellé:

<?php

/**
 * @param array{id: string, name: string, ...} $user
 * @return array{id: string, name: string, ...}
 */
function takesUserData(array $user): array {
  $user['extra_data'] = new stdClass();
  return $user;
}

Cela suit le comportement de ... en Hack code.

Psalm évitera que la valeur retournée par la fonction takesUserData (avec un tableau descellé) soit utilisée dans un appel à implode:

<?php

/**
 * @param array{id: string, name: string, ...} $user
 * @return array{id: string, name: string, ...}
 */
function takesUserData(array $user): array {
  $user['extra_data'] = new stdClass();
  return $user;
}

$foo = ['id' => 'DP42', 'name' => 'Douglas Adams'];
echo implode('', takesUserData($foo));

Qu'est-ce que ça signifie pour vous? Probablement rien! Le code de Psalm contient beaucoup de tableaux clé/valeurs, mais un seul autorise des éléments supplémentaires. Nous espérons que l'impact de cette mise à jour sera extrêmement faible.

Quoi d'autre dans Psalm 5?

Nous avons ajouté le support tant attendu pour les intersections de types et pour d'autres fonctionnalités de PHP 8.

Psalm 5 ajoute également de nouveaux types:

Ces types aident à détecter beaucoup plus de bugs et corriger un tas de faux-négatifs en vous permettant de décrire votre code plus précisément.

Sous le capot, nous avons fait de nombreux changements dans le cœur de Psalm. Le système de typage est désormais immuable, ce qui corrige un ensemble de bugs liés à la parallélisation et améliore les performances par 15-20% en simple-thread et en multi-thread (principalement en réduisant l'usage de __clone).

Nous avons également retiré le support pour les API de plugins historiques (ajoutées depuis Psalm 3) dans la mesure où les nouvelles API sont disponibles depuis quelques années.

Psalm est un gros projet, avec beaucoup à faire — si vous voulez participer, il y a beaucoup que vous pouvez faire pour aider, y compris tout un tas de problèmes pour les développeurs qui ne connaissent rien à Psalm!

Dans les prochains mois, nous allons travailler sur le support complet de PHP 8.2 et plus encore!