Проблема заключается в том, что требования borrow checker к времени жизни структуры можно обойти с помощью присвоения ковариантных полей.
В качестве примера кода, демонстрирующего ошибку, приведён (ссылка на Rust playground; для запуска нужно нажать кнопку “Run”):
struct Q<T, F: FnMut(&T)>(Option<T>, F);
impl<T, F: FnMut(&T)> Drop for Q<T, F> {
fn drop(&mut self) {
self.1(self.0.as_ref().unwrap())
}
}
fn main() {
let mut out: Option<&'static _> = None;
{
let l = vec![vec![1]];
let mut q = Q(None, |s| {
out = Some(*s);
});
q.0 = Some(&l);
}
println!("{:?}", out);
}
Обнаружение unsoundness (ошибок, приводящих к нарушению гарантий компилятора) в borrow checker’е Rust — не самое необычное явление. Но эта ошибка примечательна тем, насколько простым может быть код, вызывающий её. Для других ошибок приходилось сильно изворачиваться, чтобы избежать проверок компилятора.
Ссылка на issue: https://github.com/rust-lang/rust/issues/164250













