Home
# Lifetimes --- ## Ressources * [The Book](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html) * [The Rustonomicon](https://doc.rust-lang.org/nomicon/lifetimes.html) --- ## Problématique ```rust compile_fail [2|3-6|7|] fn main() { let r; { let x = 5; r = &x; } println!("r: {}", r); } ``` --- ## Durée de vie: annotation ```rust compile_fail [] fn main() { let r: &'a i32; // --------+-- 'a { // | let x: 'b i32 = 5; // -+--'b | r = &'b x; // | | } // -+ | println!("r: {}", r); // --------+ // x vit plus } ``` * Correction? --- ## Inférence * Souvent la durée de vie est **inférée**, * Comme pour les **types**, on doit préciser quand il y a un **doute**, * Utile que pour la **compilation**: the famous *borrow checker*, * Si vous devez annoter votre code, il se peut que vous fassiez un truc trop compliqué. --- ## Exemple ```rust compile_fail [8-13|1,7|] fn longest(x: &str, y: &str) -> &str { if x.len() > y.len() { x } else { y } } // return lifetime is... x or y? fn main() { let string1 = String::from("abcd"); let string2 = "xyz"; let result = longest(string1.as_str(), string2); println!("The longest string is {}", result); } ``` --- ## Correction ```rust [1,7|] fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } // all have the same lifetime fn main() { let string1 = String::from("abcd"); let string2 = "xyz"; let result = longest(string1.as_str(), string2); println!("The longest string is {}", result); } ``` --- ## Annotation * Indique au compilateur les relations de durées de vie, * Ne permet pas d'augmenter une durée de vie, * Le compilateur vérifie que la durée de vie est **compatible** avec la durée de vie. ```rust ignore [] &T // référence &'a T // référence avec durée de vie a &'a mut T // référence mutable avec durée de vie a ``` --- ## Dans une structure ```rust [1-3|6-8|] struct VecView<'a> { view: &'a [i32] } fn main() { let v = vec![1, 2, 3, 4, 5, 6]; let vv = VecView { view: &v[1..4], }; println!("view = {:?}", vv.view); } ``` * Le compilateur vérifie que `VecView` ne vit pas plus longtemps que sa référence `view`. --- ## Élision: fonction ```rust fn vecview(v: &[i32], min: usize, max: usize) -> &[i32] { &v[min..max] } ``` * Règle 1: Chaque référence en argument à sa durée de vie, * Règle 2: Si unique durée de vie en argument, la sortie obtient la même --- ## Élision: méthode ```rust [1-3|4-9|] struct VecView<'a> { view: &'a [i32] } impl<'a> VecView<'a> { fn show(&self, original: &[i32]) -> &[i32] { println!("we view {:?}, from {:?}", self.view, original); self.view } } fn main() { let v = vec![1, 2, 3, 4, 5, 6]; let vv = VecView { view: &v[1..4] }; vv.show(&v); } ``` * Règle 3: Si un argument est `&self` ou `&mut self`, la sortie a automatiquement la même durée de vie.