Lifetimes in Data Structures
If a data type stores borrowed data, it must be annotated with a lifetime:
1. #[derive(Debug)]
2. struct Highlight<'doc>(&'doc str);
4. fn erase(text: String) {
5. println!("Bye {text}!");
6. }
8. fn main() {
9. let text = String::from("The quick brown fox jumps over the lazy dog.");
10. let fox = Highlight(&text[4..19]);
11. let dog = Highlight(&text[35..43]);
12. // erase(text);
13. println!("{fox:?}");
14. println!("{dog:?}");
15. }
- In the above example, the annotation on
Highlightenforces that the data underlying the contained&strlives at least as long as any instance ofHighlightthat uses that data. - If
textis consumed before the end of the lifetime offox(ordog), the borrow checker throws an error. - Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes them somewhat harder to use.
- When possible, make data structures own their data directly.
- Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases.
