# Le type never de PHP 8.1 pour une méthode qui interrompt toujours l’exécution

> Une méthode de garde qui redirige ou lève systématiquement une exception gagne en clarté avec le type never dans sa signature, introduit par PHP 8.1.

- Auteur : WordPress Développement
- Publié le : 2023-10-26
- Mis à jour le : 2023-10-26
- Catégorie : Extensions
- URL : https://www.wpmoderne.fr/extensions/type-never-php-81-methode-interrompt/

## L’essentiel

- never signale qu'une fonction ne rend jamais la main normalement
- L'analyseur statique détecte le code mort placé après un tel appel
- Différent de void, qui autorise un retour sans valeur

PHP 8.1, publié fin novembre 2021, introduit un type de retour peu spectaculaire mais redoutablement précis : `never`. Une fonction déclarée avec ce type ne rend jamais la main à l'appelant, ni en renvoyant une valeur, ni même en terminant normalement son exécution : elle lève systématiquement une exception, appelle `exit`, ou redirige puis interrompt le script.

Ce type se distingue de `void`, qui signifie qu'une fonction ne renvoie aucune valeur utile mais continue normalement son exécution jusqu'à sa fin. La nuance, subtile en apparence, change concrètement ce qu'un analyseur statique peut déduire du code qui suit l'appel de la fonction.

## Le cas d'usage typique : une méthode de garde

Dans une extension qui protège l'accès à un écran d'administration personnalisé, une méthode de garde vérifie une condition et interrompt systématiquement l'exécution si elle échoue, par exemple en refusant l'accès ou en redirigeant vers une autre page.

```
final class GardeAcces
{
    public static function exigerCapacite( string $capacite ): never
    {
        if ( current_user_can( $capacite ) ) {
            return;
        }

        wp_die( 'Accès refusé.', 403 );
    }
}
```

Cette signature contient volontairement une incohérence apparente : le corps de la méthode contient un `return;` sans valeur dans le cas où la vérification réussit, alors que le type déclaré est `never`. En réalité, PHP interdit ce cas de figure : une méthode typée `never` ne doit jamais contenir de `return`, même vide, sous peine d'erreur fatale à l'exécution. La méthode ci-dessus doit être corrigée pour ne jamais retourner normalement.

## Une signature cohérente avec never

> L'essentiel à retenir : never signale qu'une fonction ne rend jamais la main normalement ; L'analyseur statique détecte le code mort placé après un tel appel ; Différent de void, qui autorise un retour sans valeur

```
final class GardeAcces
{
    public static function exigerCapacite( string $capacite ): void
    {
        if ( ! current_user_can( $capacite ) ) {
            self::refuser();
        }
    }

    private static function refuser(): never
    {
        wp_die( 'Accès refusé.', 403 );
    }
}
```

Ici, `refuser()` porte légitimement le type `never` : elle ne fait qu'appeler `wp_die()`, qui termine l'exécution du script (en dehors du contexte de test unitaire, où son comportement est filtrable). La méthode publique `exigerCapacite()`, elle, reste typée `void`, car elle peut légitimement rendre la main normalement si la capacité est présente.

## Ce que l'analyseur statique en déduit

L'intérêt principal de `never` ne se voit pas à l'exécution, mais à l'analyse statique du code, via des outils comme PHPStan ou Psalm. Un appel à une fonction typée `never` signale à l'outil que tout le code placé après cet appel, dans le même bloc, est inatteignable :

```
function traiter_requete( ?WP_User $utilisateur ): string {
    if ( null === $utilisateur ) {
        GardeAcces::refuser(); // typée never
    }

    // À partir d'ici, l'analyseur sait que $utilisateur n'est plus null.
    return $utilisateur->display_name;
}
```

Sans le type `never`, un analyseur statique strict continuerait de considérer que `$utilisateur` peut valoir `null` à la ligne suivante, et signalerait une erreur potentielle sur l'accès à `display_name`. Le type `never` élimine cette fausse alerte en documentant explicitement, au niveau du langage, que le flux d'exécution ne peut pas se poursuivre au-delà de l'appel.

## Pièges à éviter

- Une méthode typée `never` ne peut contenir aucun `return`, même sans valeur : PHP lève une erreur fatale si ce cas se présente.
- Le type `never` n'est pas compatible avec une interface qui déclarerait la même méthode en `void` : la covariance de type l'autorise dans un sens (une classe fille peut resserrer `void` en `never`), pas dans l'autre.
- Une boucle infinie sans `exit` ni exception ne justifie pas `never` à elle seule : le type concerne l'absence de retour à l'appelant, pas la durée d'exécution.

> Le repère que je retiens pour choisir entre `void` et `never` : si un lecteur pressé du code peut légitimement se demander « et si la fonction revient quand même ? », c'est que `never` apporte une clarté que `void` ne donne pas.

## En résumé

Le type `never`, disponible depuis PHP 8.1, documente précisément qu'une fonction interrompt systématiquement l'exécution, avec un bénéfice concret pour l'analyse statique du code qui suit son appel. Ce sujet porte sur la déclaration de ce type précis ; la gestion d'erreurs dans son ensemble, avec les exceptions et leur hiérarchie, reste un sujet bien plus large qui dépasse cette seule annotation.
