Советую почитать вот эту статью:
https://habr.com/ru/articles/515034/
А вообще, времена жизни - это часть типа.
Условный u32 имеет время жизни 'static
А ссылка на u32 - &'a u32 (где 'a это диапазон от объявления исходного u32 до его последнего использования) будет иметь время жизни 'a
Пример по сложнее, ссылка на ссылку - &'a &'b u32 - будет иметь время жизни наименьшее из 'a и 'b
Передаётся через дженерик, так как функция должна работать с абстрактным временем жизни
fn example<'a>(r: &'a u32) -> &'a u32 { r }
fn f_a() {
let a = 1;
let r = example(&a);
}
fn f_b() {
let b = 1;
let r = example(&b);
}
В этом примере очевидно что переменная a в f_a будет иметь время жизни отличное от b в f_b, но example спокойно работает и с тем и с другим, то есть она является обобщённой по времени жизни, в первом случае она вернёт ссылку с временем жизни как у переменной a, во втором - как у b.
А ещё помимо времен жизни и типов в дженериках могут быть некоторые константы:
fn make_array<const SIZE: usize>(el: u32) -> [u32; SIZE] {
[el; SIZE]
}
let arr = make_array::<3>(1); // [1, 1, 1]