Introduction
Le déplacement d’une String transfère sa propriété, mais de nombreuses fonctions ont seulement besoin d’y accéder temporairement. Rust appelle cet accès temporaire un emprunt et le représente avec une référence.
Vous allez terminer un programme préparé de gestion de liste d’invités en trois petites étapes : inspecter du texte possédé par l’intermédiaire d’une référence partagée, observer volontairement pourquoi un accès partagé ne permet pas de le modifier, puis effectuer une mise à jour contrôlée au moyen d’une référence mutable. La sortie finale prouvera que main possède toujours la liste et peut encore l’utiliser.
Inspecter des données avec une référence partagée
Dans cette étape, vous allez donner à une fonction un accès en lecture seule à une String au lieu de lui transférer la propriété.
Accédez au projet Cargo préparé et ouvrez son code source :
cd /home/labex/project/guest-borrowing
nano src/main.rs
La configuration a créé le projet complet et laissé un emplacement réservé dans l’appel à inspect_guests. Le type de son paramètre est &String. Le symbole & signifie « une référence vers une String » : la fonction peut consulter temporairement la valeur, mais elle n’en devient pas propriétaire.
Remplacez uniquement /* Step 1: borrow guest_list */ par &guest_list, afin que l’appel devienne :
inspect_guests(&guest_list);
Ici, &guest_list crée une référence partagée. Une référence partagée permet de partager un accès en lecture seule sans transférer la String elle-même.
Enregistrez avec Ctrl+O, appuyez sur Entrée, puis quittez avec Ctrl+X. Exécutez le programme :
cargo run --quiet
La sortie doit être :
Inspecting: Ari, Bo
Caller still owns: Ari, Bo
Before update: Ari, Bo
Updated: Ari, Bo
La première ligne provient de la référence empruntée. La deuxième ligne constitue la preuve importante concernant la propriété : après le retour de inspect_guests, main peut toujours utiliser guest_list. La fonction de mise à jour lit également la valeur actuelle, mais ne la modifie pas encore.
Observer la limite d’une référence partagée
Dans cette étape, vous allez essayer volontairement de modifier la String par l’intermédiaire d’une référence partagée. L’échec de la vérification par le compilateur est attendu et vous fournit une preuve de la règle d’emprunt de Rust.
Ouvrez à nouveau le code source :
nano src/main.rs
Dans add_guest, supprimez uniquement les // placés au début de la ligne préparée, afin qu’elle devienne :
list.push_str(", Mina");
La méthode push_str ajoute du texte à une String ; elle doit donc pouvoir modifier la valeur. Cependant, list est actuellement de type &String, ce qui autorise uniquement un accès partagé en lecture seule.
Enregistrez et quittez. Avant d’effectuer la vérification, prévoyez le résultat : le compilateur doit refuser la modification tentée, car une référence partagée ne peut pas fournir un accès mutable.
Lancez la vérification. Un échec est attendu :
cargo check
Repérez les éléments stables suivants du diagnostic :
error[E0596]: cannot borrow `*list` as mutable, as it is behind a `&` reference
...
consider changing this to be a mutable reference
La formulation *list désigne la String accessible par l’intermédiaire de la référence. Rust ne dit pas que la String ne pourra jamais changer ; il indique que cette &String particulière ne donne pas l’autorisation de la modifier. Vous accorderez un accès mutable contrôlé à l’étape suivante.
Mettre à jour des données avec une référence mutable
Dans cette étape, vous allez donner à add_guest une autorisation temporaire et exclusive de modifier la String de l’appelant.
Une référence mutable s’écrit &mut T. Une règle utile pour débuter est la suivante : plusieurs lecteurs ou un seul écrivain à la fois. Les références partagées permettent la lecture, tandis qu’une référence mutable accorde temporairement un accès exclusif en écriture. Cette exclusivité empêche deux parties du programme de modifier la même valeur de manière inattendue.
Ouvrez le fichier :
nano src/main.rs
Effectuez trois modifications ciblées :
- Remplacez le type du paramètre de
add_guest, de&Stringpar&mut String. - Ajoutez
mutà la liaison afin d’obtenirlet mut guest_list = .... - Remplacez l’appel à
add_guest, de&guest_listpar&mut guest_list.
La signature complète de la fonction et l’appel doivent avoir les formes suivantes :
fn add_guest(list: &mut String) {
add_guest(&mut guest_list);
Les deux utilisations de mut sont liées, mais remplissent des rôles différents. let mut guest_list indique que la valeur possédée peut être modifiée. &mut guest_list crée ensuite une référence mutable temporaire qui prête à `add_guest un accès exclusif en écriture pendant toute la durée de l’appel.
Enregistrez et quittez, puis vérifiez la correction :
cargo check
Un résultat Finished sans erreur E0596 signifie que les autorisations sont maintenant cohérentes. Exécutez le programme :
cargo run --quiet
La sortie finale doit être :
Inspecting: Ari, Bo
Caller still owns: Ari, Bo
Before update: Ari, Bo
Updated: Ari, Bo, Mina
L’emprunt mutable prend fin lorsque add_guest retourne. Le dernier affichage peut de nouveau lire guest_list, ce qui prouve que la propriété est restée dans main tandis que la fonction effectuait une mise à jour contrôlée.
Résumé
Vous avez utilisé &String pour un accès partagé en lecture seule et &mut String pour une modification temporaire et exclusive. Dans les deux cas, l’appelant a conservé la propriété, et le compilateur a contribué à faire respecter la différence entre consulter et modifier des données empruntées.



