Rust : Comment comparer String avec des littéraux de chaîne (match)

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi Rust ne permet-il pas simplement de comparer String avec "bonjour" ?

\n\n

Si vous commencez tout juste à apprendre Rust et que vous avez déjà rencontré la nécessité de faire correspondre une variable de type String avec un littéral de chaîne comme "hello" ou "world", vous avez sûrement vu une étrange erreur du compilateur. Vous écrivez quelque chose comme :

\n\n
let user_input = String::from("start");\nmatch user_input {\n    "start" => println!("On commence !"),\n    "stop"  => println!("On s'arrête !"),\n    _       => println!("Commande inconnue"),\n}\n
\n\n

Et le compilateur affiche quelque chose comme : "expected struct `String`, found `&str`". Cela vous dit quelque chose ?

\n\n

Sur Stack Overflow, la question "How to match a String against string literals?" a recueilli des milliers de vues — c'est une vraie difficulté pour les débutants. Dans cet article, nous allons voir pourquoi cela se produit et vous montrer trois façons simples de résoudre le problème. Vous apprendrez comment fonctionne le système de possession et d'emprunt en Rust en pratique, et vous cesserez d'avoir peur des erreurs du compilateur.

\n\n

Nature du conflit : String vs &str

\n\n

Pour comprendre le problème, il faut revenir aux bases. En Rust, il existe deux types principaux pour travailler avec du texte :

\n\n
    \n
  • String — c'est une chaîne possédée, stockée sur le tas. Elle peut être modifiée, grandir et rétrécir. Exemple : let s = String::from("hello");
  • \n
  • &str — c'est une tranche de chaîne. C'est une référence vers une partie d'une chaîne (ou vers un littéral de chaîne, stocké directement dans le binaire du programme). Exemple : "hello" est précisément un &'static str.
  • \n
\n\n

Lorsque vous écrivez match user_input { "start" => ... }, vous essayez de comparer un String avec un &str. Le compilateur dit : "Je ne sais pas comment les faire correspondre directement, les types sont différents !". Et c'est une bonne chose — Rust vous protège des conversions implicites qui pourraient entraîner une perte de performance ou des bugs cachés.

\n\n

Mais alors, comment faire ? Il existe trois solutions simples et élégantes.

\n\n

Solution 1 : Emprunt via as_str()

\n\n

La manière la plus directe et compréhensible est d'obtenir une tranche de chaîne (&str) à partir d'un String en utilisant la méthode as_str(). Cette méthode retourne une référence au contenu de la chaîne, sans la copier. Cela ressemble à ceci :

\n\n
fn main() {\n    let command = String::from("start");\n\n    match command.as_str() {\n        "start" => println!("Démarrage du système..."),\n        "stop"  => println!("Arrêt..."),\n        "pause" => println!("Pause..."),\n        _       => println!("Commande inconnue : {}", command),\n    }\n}\n
\n\n

Pourquoi cela fonctionne-t-il ? as_str() retourne un &str, qui peut maintenant être comparé aux littéraux. Rust voit que les deux opérandes sont des &str, et la correspondance de motifs fonctionne parfaitement.

\n\n

Avantages : simplicité, lisibilité, zéro surcoût (emprunt, pas de copie).

\n\n

Inconvénients : il faut penser à appeler la méthode. Mais c'est un détail.

\n\n

Solution 2 : Comparaison dans une condition if

\n\n

Si vous n'avez pas besoin de toute la puissance de match, vous pouvez utiliser des if classiques avec la méthode eq() ou l'opérateur ==. Rust sait comparer String et &str via le trait PartialEq, qui est implémenté pour cette paire de types.

\n\n
fn main() {\n    let user_input = String::from("admin");\n\n    if user_input == "admin" {\n        println!("Accès autorisé !");\n    } else if user_input == "guest" {\n        println!("Accès invité");\n    } else {\n        println!("Identifiant incorrect");\n    }\n}\n
\n\n

Cela fonctionne parce que le compilateur convertit automatiquement String en &str lors de la comparaison. Mais dans match, cette conversion n'a pas lieu — une correspondance exacte est requise.

Blogs

Book Recommendations