Comment réussir un entretien Rust : les meilleures questions de niveau avancé
\n\nRust est un langage de programmation système qui gagne en popularité grâce à sa sécurité, ses performances et l'absence de ramasse-miettes. Si vous avez déjà maîtrisé les bases et vous préparez à un entretien pour un poste de développeur Rust Senior ou Middle, vous devrez faire face à des questions qui dépassent la simple syntaxe. Dans cet article, nous analyserons les sujets avancés clés qui reviennent souvent lors des entretiens techniques.
\n\nNous aborderons quatre blocs : la possession et l'emprunt (ownership & borrowing), les durées de vie (lifetimes), le code non sécurisé (unsafe) et les macros, ainsi que le multithreading avancé. Chaque section contient des questions réelles et des exemples de code.
\n\n1. Possession, emprunt et règles de mutabilité
\n\nQuestion : Expliquez comment fonctionne le mécanisme de possession en Rust. Quelle est la différence entre &T, &mut T et Box<T> ?
Réponse : La possession est le fondement de la sécurité mémoire en Rust. Chaque valeur a exactement un propriétaire. Lorsque le propriétaire sort de la portée, la valeur est détruite. L'emprunt (&T) permet de « prêter » temporairement une référence aux données sans transférer la possession. L'emprunt mutable (&mut T) donne le droit de modifier les données, mais uniquement en l'absence d'autres références.
Box<T> est un pointeur intelligent qui alloue de la mémoire sur le tas. Il transfère la possession, ce qui le distingue des simples références.
fn main() {\n let mut s = String::from("Bonjour");\n let r1 = &s; // référence immuable\n let r2 = &mut s; // Erreur ! impossible d'avoir &mut et & en même temps\n // println!("{}", r1);\n}\n\n\nQuestion : Qu'est-ce que la « règle d'un seul emprunt mutable » ?
\n\nRéponse : À tout moment, une valeur peut avoir soit une référence mutable, soit un nombre quelconque de références immuables, mais pas les deux en même temps. Cela empêche les courses de données à la compilation.
\n\n2. Durées de vie (Lifetimes) — comment le compilateur comprend qu'une référence est valide
\n\nQuestion : Pourquoi les annotations de durée de vie sont-elles nécessaires ? Donnez un exemple où elles sont obligatoires.
\n\nRéponse : Les annotations de durée de vie ('a, 'b, etc.) aident le compilateur à vérifier que toutes les références sont valides. Elles sont obligatoires lorsqu'une fonction retourne une référence liée à l'un des paramètres d'entrée et que le compilateur ne peut pas déduire automatiquement la durée de vie.
// Fonction retournant la chaîne la plus longue\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\n\nfn main() {\n let s1 = String::from("longue");\n let result;\n {\n let s2 = String::from("courte");\n result = longest(&s1, &s2); // ok\n }\n // println!("{}", result); // Erreur : s2 est morte\n}\n\n\nQuestion : Qu'est-ce que « l'élision de durée de vie » (lifetime elision) ?
\n\nRéponse : Le compilateur ajoute automatiquement des annotations de durée de vie dans les cas simples. Par exemple, pour la méthode fn first_word(s: &str) -> &str, le compilateur comprend lui-même que la durée de vie de sortie est égale à celle d'entrée. L'élision fonctionne selon trois règles décrites dans le livre Rust.
3. Rust unsafe et macros
\n\nQuestion : Quand l'utilisation de unsafe est-elle justifiée ? Quelles opérations ne sont disponibles qu'à l'intérieur des blocs unsafe ?
Réponse : unsafe est utilisé pour des opérations que le compilateur ne peut pas vérifier : déréférencement de pointeurs bruts, appel de fonctions externes (FFI), accès à des variables statiques mutables, implémentation de traits non sécurisés. Cependant, unsafe n