Introduction : l'énigme des deux « mut »
\nSi vous avez déjà programmé en Rust, vous avez sûrement remarqué la curieuse dualité du mot-clé mut. Il peut se placer aussi bien avant le nom de la variable (let mut x = 5) qu'après les deux-points, à côté du type (&mut T). À première vue, un détail, mais sur Stack Overflow, ce sujet a accumulé des milliers de vues. Pourquoi ? Parce que derrière ce détail se cache une différence fondamentale entre la propriété et la référence.
Dans cet article, nous ne répondrons pas simplement à la question « où placer mut ? ». Nous allons regarder sous le capot de Rust, analyser comment le compilateur gère la mutabilité, et pourquoi cette distinction est la clé d'une gestion sécurisée de la mémoire. Si vous apprenez Rust ou souhaitez approfondir son modèle de propriété, vous êtes au bon endroit.
\n\nPartie principale : deux mondes — deux mut
\n1. Premier mut : « Je suis le propriétaire et je peux changer »
\nLorsque vous écrivez :
\nlet mut x = 42;\nx = 10; // ok\n\nvous dites au compilateur : « Je crée une variable x qui possède la valeur 42, et j'autorise la modification de cette valeur par la suite ». Sans mut, la variable est immuable par défaut. C'est un choix de conception délibéré de Rust : par défaut, la sécurité, et la mutation est une autorisation explicite.
Sous le capot : le compilateur alloue de l'espace sur la pile (ou le tas, s'il s'agit d'un Box) et marque la cellule mémoire comme « modifiable ». Le vérificateur d'emprunt (borrow checker) veillera à ce que vous n'ayez pas simultanément des références modifiables et immuables vers cette mémoire. Si mut n'était pas présent, toute tentative d'affectation d'une nouvelle valeur provoquerait une erreur de compilation.
2. Deuxième mut : « Je te donne les clés, mais pas la maison »
\nPrenons maintenant un exemple avec une référence :
\nlet mut x = 42;\nlet y = &mut x; // référence modifiable vers x\n*y = 100;\n\nIci, &mut T ne concerne pas la propriété, mais l'emprunt. Nous disons : « Je prête x à la variable y, et je donne le droit de le modifier ». x reste le propriétaire, mais transfère temporairement le contrôle.
Différence clé : mut après les deux-points se rapporte au type de la référence, et non à la variable. Vous ne pouvez pas écrire let &mut x = &y — c'est syntaxiquement incorrect. Rust distingue strictement :
- \n
let mut x— une variable propriétaire modifiable \n&mut T— une référence modifiable vers une valeur de type T \n
C'est précisément cette distinction qui perturbe les débutants : visuellement, « mut » se trouve à des endroits différents, mais sémantiquement, il résout des problèmes différents.
\n\n3. Pourquoi c'est important : le borrow checker
\nImaginez que vous écriviez une fonction qui prend une référence :
\nfn increment(n: &mut i32) {\n *n += 1;\n}\n\nfn main() {\n let mut a = 5;\n increment(&mut a);\n println!("{}", a); // 6\n}\n\nSi nous avions écrit fn increment(n: &i32) (sans mut), nous n'aurions pas pu modifier n. Et si nous avions oublié mut pour a, nous n'aurions pas pu passer une référence modifiable. Le compilateur Rust vous protège contre les modifications accidentelles de données qui pourraient entraîner des courses de données ou un comportement indéfini.
Sous le capot : &mut T est une référence unique (exclusive). À tout moment, il ne peut exister qu'une seule référence modifiable vers les données. Cette règle garantit que personne d'autre ne lit les données pendant que vous les modifiez. Les références immuables peuvent être en nombre illimité — elles ne font que lire.
4. Exemple concret de la pratique : structures et méthodes
\nLa confusion survient souvent lors du travail avec des méthodes :
\nstruct Point {\n x: i32,\n y: i32,\n}\n\nimpl Point {\n fn shift(&mut self, dx: i32, dy: i32) {\n self.x += dx;\n self.y += dy;\n }\n}\n\nfn main() {\n let mu