Почему тут переменная считается одолженной?

Увидел это какое-то время назад в англоязычном телеграм чате и все никак не могу как следует осознать. Есть такой код:

#[derive(Debug)]
struct X<'a> {
    a: i32,
    b: &'a i32,
}

#[allow(unused)]
fn main() {
    let mut x = X { a: 1, b: &0 };
    let mut y = 2;
    x.b = &y;
    x.b = &0;
    y = 3;
    println!("x: {:?}", x.b);
}

и он не собирается с вот такой ошибкой:

error[E0506]: cannot assign to `y` because it is borrowed
  --> src/main.rs:13:5
11 |     x.b = &y;
   |           -- borrow of `y` occurs here
12 |     x.b = &0;
13 |     y = 3;
   |     ^^^^^ assignment to borrowed `y` occurs here
14 |     println!("x: {:?}", x.b);
   |                         --- borrow later used here

И, вроде, понятно, что это завязанный на структуру 'a виноват и понятно что это меняет время жизни y, но почему именно y считается одолженным в этой ситуации?

Видел похожий вопрос на SO - https://stackoverflow.com/questions/69541461/are-there-any-restrictions-when-using-a-reference-in-a-field-of-a-struct - но тоже как-то не очень помогает глубокое понимание того как реально работает одалживание составить. Может кто-то может пояснить?

Похоже, вариант от @Kolsky лучше всего поясняет как именно оно происходит:

  1. X живёт 'a;
  2. Лайфтайм &0 свободно сокращается до 'a;
  3. Одалживаем y, следовательно, 'a живёт максимум как скоуп функции, и одалживание y становится 'a;
  4. x живёт и валидна как минимум до строчки с println;
  5. 'a продлевается до println;
  6. y, одолженное на 'a, было перезаписано раньше срока одалживания.

Типа можно было бы усложнить анализ NLL для !Drop и сказать, что часть полей всё ещё доступна после окончания лайфтайма, но тут уже семантика слегка изменится