Use-after-free is not the only danger. With the wrong lifetime, you can cause variable smoothing. Take this (contrived) function as an example:
fn duplicate_mut_slice<'a, T>(xs: &mut [T]) -> &'a mut [T] { let ptr = xs.as_mut_ptr(); // btw, this part is safe! unsafe { std::slice::from_raw_parts_mut(ptr, xs.len()) } }
Due to how life lines are built, challenges like this will succeed:
fn alias_first_element<T>(xs: &mut [T]) -> (&mut T, &mut T) { let a = duplicate_mut_slice(xs); let b = duplicate_mut_slice(xs); (&mut a[0], &mut b[0]) }
Note that in this second function signature, the lifetimes are correct, and using the day after tomorrow is not a (immediate) danger. But mutable smoothing is very insidious. Basically, everything depends on the guaranteed absence of variable smoothing to prevent problems such as race conditions, iterator invalidity, logical errors and, indeed, useless (something controlled by T ). You can cause almost any problem that is possible with a mutable alias.
delnan
source share