IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Les erreurs du compilateur Rust les plus couramment rencontrées dans RustRover


précédentsommaire

II. Identification des erreurs les plus courantes à partir des données d’utilisation de RustOver – Partie 2

Les données d’utilisation de RustRover nous ont permis d’identifier les 10 erreurs du compilateur Rust les plus fréquentes, que nous avons commencé à examiner dans une première partieIdentification des erreurs les plus courantes à partir des données d’utilisation de RustOver – Partie 1. Dans cette seconde partie de l’article, nous poursuivons avec l’examen du top 5 de ces erreurs et abordons les aspects du langage Rust qui posent le plus de problèmes aux développeurs avec le compilateur.

II-1. Erreur fréquente n° 5 : E0433 (utilisation d’une crate, d’un module ou d’un type non déclaré)

Cette erreur est semblable à l’erreur E0432 (une importation n’a pas été résolue), que nous avons vue dans l’article précédent. La seule différence ici est qu’un chemin avec un composant problématique est utilisé directement dans un nom, sans la clause use. 17,5 % des utilisateurs de RustRover ont rencontré cette erreur. Dans l’exemple de code ci-dessous, le compilateur ne comprend pas s’il s’agit d’une crate ou d’un module et nous le fait savoir :

Image non disponible

Cet exemple montre pourquoi les messages d’erreur de Rust sont autant appréciés. Même sans lire le message, le correctif à apporter est évident : vérifier les noms, ajouter les dépendances requises à Cargo.toml si nécessaire ou introduire les importations appropriées.

De son côté, RustRover permet de choisir les noms importés.

Image non disponible

Image non disponible

L’utilisation de la saisie semi-automatique de code permet d’éviter cette erreur.

II-2. Erreur fréquente n° 4 : E0425 (un nom non résolu a été utilisé)

Poursuivons avec une autre erreur de la catégorie « non résolu ». 20,5 % des utilisateurs de RustRover ont déjà été dans une situation dans laquelle ils ont utilisé un nom non résolu, qui n’était syntaxiquement ni une crate ni un module. Voici ce que l’ont peut voir lorsque cette erreur survient :

Image non disponible

Évidemment, lorsque cela arrive, le contexte n’est pas toujours aussi simple que dans cet exemple.

Hélas, même l’excellent compilateur de Rust n’est pas d’une grande aide face à cette erreur. Plusieurs approches sont possibles ici : réviser le nom, fournir une définition ou introduire des importations correctes.

II-3. Erreur fréquente n° 3 : E0599 (une méthode est utilisée sur un type qui ne l’implémente pas)

Au risque de gâcher la surprise, à partir de maintenant, toutes les erreurs porteront sur la vérification de type ! En effet, les trois erreurs les plus fréquentes sont toutes liées à une utilisation de type incorrecte. Concernant l’erreur n° 3, 27,5 % des utilisateurs de RustRover ont tenté d’appeler une méthode sur une valeur de type qui n’implémente pas cette méthode. Examinons l’exemple suivant :

 
Sélectionnez
fn main() {
   let numbers: Vec = vec![4, 11, 15, 12];
   let sum: usize = numbers.sum();
   println!(GUILLEMET-KITOOODVPAnswer = {sum}GUILLEMET-KITOOODVP);
}

Tout semble correct, sauf qu’il n’y a pas de méthode sum pour Vec. Voici le contenu exact du message d’erreur :

error[E0599]: `Vec` is not an iterator

Dans ce cas, il faut appeler une méthode iter en premier, puis utiliser sum sur l’itérateur résultant.

RustRover dispose d’une fonctionnalité qui permet d’éviter ce genre d’erreurs : la saisie semi-automatique chaînée. Voici un exemple de ce que cela donne :

Image non disponible

Lorsque la suggestion de saisie semi-automatique est acceptée, les méthodes iter et sum sont ajoutées à la chaîne d’appels, ce qui corrige immédiatement le code.

En général, la saisie semi-automatique évite de recevoir un message d’erreur E0599. Si vous ne voyez pas de suggestion pour appeler la méthode dont vous avez besoin, il est possible que le problème réel provienne en réalité du fait que le type de l’appelé est incorrect.

Un autre aspect de cette méthode vaut la peine d’être mentionné : dans de nombreux contextes, vous avez le contrôle sur vos propres déclarations de type. Vous pouvez notamment appeler une méthode en premier et demander ensuite à RustRover de procéder au scaffolding de son implémentation en appuyant sur Alt-Entrée (⌥Option–Retour) et en exécutant l’action suggérée :

Image non disponible

Suite à cette action, RustRover génère le modèle d’implémentation de la méthode en prenant en compte les informations contextuelles concernant les types :

 
Sélectionnez
impl Info {
   pub(crate) fn summary(&self) -> String {
       todo!()
   }
}

L’exécution de ce code résulte en une erreur d’exécution, mais au moins le compilateur n’y trouve rien à redire.

II-4. Erreur fréquente n° 2 : E0308 (le type attendu ne correspondait pas au type reçu)

Imaginez que vous utilisiez une expression de type A dans un contexte où une valeur de type B est attendue. Ici, la notion de « contexte » peut désigner plusieurs choses, comme un paramètre de fonction sur un site d’appel, une déclaration de variable ou une instruction/expression de contrôle du flux. 30 % des utilisateurs de RustRover ont déjà été dans cette situation.

D’un point de vue conceptuel, deux choix s’offrent à nous dans ce cas : modifier une valeur ou modifier le contexte. La modification d’une valeur peut impliquer le typage, le référencement/déréférencement, l’appel d’une méthode de transformation ou son remplacement par quelque chose d’autre. On ne peut pas toujours agir sur le contexte, mais il est parfois possible de modifier le type attendu pour qu’il corresponde au type reçu.

RustRover prend en charge les deux modes opératoires en fournissant plusieurs correctifs rapides, par exemple :

Image non disponible

Notez la deuxième suggestion dans la liste : dans ce cas, RustRover a suggéré une transformation assez sophistiquée d’une valeur qui convient au compilateur. Suivre la première suggestion corrigerait le contexte, à savoir la définition de la fonction.

II-5. Erreur fréquente n° 1 : E0277 (vous avez essayé d’utiliser un type qui n’implémente pas de trait à un endroit où un trait est attendu)

Enfin, nous arrivons à la 1re place du classement ! L’erreur du compilateur Rust la plus fréquemment rencontrée dans RustRover est E0277. 32 % des utilisateurs de RustRover ont fait l’expérience de cette situation cauchemardesque mêlant types et traits. L’explication officielle fait un bon travail en fournissant des exemples et des explications des correctifs possibles. Ici, nous allons observer le comportement de RustRover.

Voici ma fonctionnalité de RustRover préférée lorsqu’il s’agit de ce genre d’erreurs :

Image non disponible

Le compilateur renvoie le message d’erreur suivant :

error[E0277]: `Info` doesn't implement `std::fmt::Display`

Bien sûr, l’implémentation du trait Display est un choix possible, et RustRover peut aider pour le scaffolding d’une implémentation. Mais dans ce cas, je préfère appliquer la première suggestion, qui comprend deux étapes simultanées :

  • dérivation d’une implémentation pour le trait Debug.
  • modification de la chaîne de format pour appeler le formatage du trait Debug.

Malheureusement, dans de nombreux autres cas, RustRover ne parvient pas à découvrir et à mettre en évidence cette erreur par lui-même. Comme mentionné dans l’article précédent, sa fonctionnalité de vérification de type n’est pas encore assez puissante, mais nous travaillons activement à son amélioration.

II-6. Observation des erreurs Rust en général

Récemment, nous avons fait un sondage auprès des membres de la communauté afin de savoir quel est l’aspect du langage causant le plus d’erreurs dans leur code, et voici les réponses que nous avons obtenues :

Image non disponible

Afin de comparer les réponses de la communauté à nos données, nous avons examiné les 25 erreurs de compilateur Rust les plus fréquentes et les avons classées en cinq grandes catégories :

  • types et traits
  • propriétés et durées de vie
  • macros
  • noms non résolus ou éléments inexistants
  • autres

Voici les résultats (numéros de code d’erreur classés par ordre croissant) :

Code de l’erreur

Description

Catégorie

E0061

Un nombre non valide d’arguments a été passé lors de l’appel d’une fonction.

Autre

E0063

Aucun champ de structure ou de variante d’énumération de type structure n’a été fourni.

non résolu/non existant

E0106

Cette erreur indique que l’un des types ne comporte pas de durée de vie.

propriété et durées de vie

E0107

Un nombre incorrect d’arguments génériques a été fourni.

types et traits

E0277

Vous avez essayé d’utiliser un type qui n’implémente pas un trait à un endroit où un trait est attendu.

types et traits

E0282

Le compilateur n’a pas pu déduire un type et a demandé une annotation de type.

types et traits

E0283

Une implémentation ne peut pas être choisie de façon claire en raison du manque d’informations.

types et traits

E0308

Le type attendu ne correspond pas au type reçu.

types et traits

E0369

Une opération binaire a été tentée sur un type qui ne la prend pas en charge.

types et traits

E0382

Une variable a été utilisée après que son contenu a été déplacé.

propriété et durées de vie

E0412

Un nom de type utilisé n’est pas dans la portée.

non résolu/non existant

E0423

Un identifiant a été utilisé comme un nom de fonction ou une valeur était attendue et l’identifiant existe, mais appartient à un espace de nom différent.

non résolu/non existant

E0425

Un nom non résolu a été utilisé.

non résolu/non existant

E0432

Une importation n’a pas été résolue.

non résolu/non existant

E0433

Une crate, un module ou un type non déclaré a été utilisé.

non résolu/non existant

E0502

Une variable déjà empruntée comme immuable a été empruntée comme mutable.

propriété et durées de vie

E0507

Une valeur empruntée a été déplacée.

propriété et durées de vie

E0515

Une référence à une variable locale a été renvoyée.

propriété et durées de vie

E0596

Cette erreur se produit parce que vous avez tenté d’emprunter de façon mutable une variable non mutable.

propriété et durées de vie

E0597

Cette erreur se produit, car une valeur a été supprimée alors qu’elle était encore empruntée.

propriété et durées de vie

E0599

Cette erreur se produit lorsqu’une méthode est utilisée pour un type qui ne l’implémente pas.

types et traits

E0609

Tentative d’accès à un champ non existant dans une structure.

non résolu/non existant

E0614

Tentative de déférencement d’une variable qui ne peut pas être déférencée.

Autre

E0658

Une fonctionnalité instable a été utilisée.

Autre

E0716

Une valeur temporaire est supprimée alors qu’un emprunt est toujours actif.

propriété et durées de vie

Malheureusement, les données dont nous disposons ne donnent pas beaucoup d’informations sur les macros. Nous ne pouvons ni détecter de façon fiable les problèmes d’expansion de macros, ni identifier d’autres erreurs résultant d’expansions de macros réussies. Cela montre que nous pourrions appliquer une catégorisation plus fine aux données que nous collectons.

En faisant abstraction des macros, aucune des 25 erreurs les plus fréquentes ne se détache véritablement, il ne semble donc pas qu’il y ait un aspect de Rust en particulier qui pose davantage problème aux développeurs :

  • types et traits – 7 erreurs
  • propriété et durées de vie – 8 erreurs
  • noms non résolus ou éléments inexistants – 7 erreurs
  • autres – 3 erreurs

II-7. Résumé

Dans ce second article, nous avons passé en revue les cinq erreurs du compilateur Rust les plus fréquemment rencontrées dans RustRover et les correctifs possibles. Trois d’entre elles se rapportent aux types et traits, ce dont on peut déduire que ces éléments ont un rôle significatif dans l’obtention d’un code Rust de meilleure qualité. En examinant des données plus générales relatives aux 25 erreurs les plus fréquentes, on voit aussi que bien d’autres aspects de Rust peuvent contribuer aux erreurs que nous rencontrons souvent.


précédentsommaire

Copyright © 2024 Vitaly Bragilevsky. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.