Почему переменная data заимствуется после вызова функции?

На stackowerflow мне объяснили как на самом деле работают времена жизни. Мне не слишком нравится эта концепция, но она объясняет что происходит в примере в шапке.
Суть вот в чем:

Длительность заимствования определяется только временем жизни в ссылке, которое вычисляется компилятором.

Компилятор в своих вычислениях конечно учитывает области видимости ссылок и обычно заимствование заканчивается, когда ссылка выходит из области видимости. Но в примере в шапке эти вычисления приводят к тому, что время жизни в ссылке должно быть равно области определения переменной data и оно больше чем область видимости ссылки на data.

Похоже, что единственная ситуация, когда явно проявляется то что заимствование может продолжаться после выхода ссылки из области видимости - это ссылка вида &'a mut T<'a>. Во всяком случае я не смог найти других примеров. Если кто-нибудь сможет - кидайте сюда.

В рамках этой концепции становится понятно, почему правила заимствования не действуют на статические переменные. Мутабельное заимствование по ссылке с временем жизни 'static должно длится вечно, и когда ссылка вышла бы из области видимости, доступ к данным был бы заблокирован навсегда.

Честно говоря не вижу смысла в такой реализации времен жизни. Назначение механизма заимствования - предотвращение гонок при изменении данных. Зачем может быть нужно продолжать блокировать доступ к данным после того, как мутабельная ссылка на эти данные, покинула область видимости? Всегда считал что время жизни в ссылке - это верхняя граница, до котрой эта ссылка может дожить, а длительность заимствования данных определяется тем, где ссылка покидает область видимости (или в случае NLL тем где ссылка последний раз использовалась).

Документация в этом вопросе не особенно вдается в подробности. Вот определение времени жизни из Растономикона:

Each reference, and anything that contains a reference, is tagged with a lifetime specifying the scope it’s valid for.

То есть время жизни определяет область в которой ссылка действительна. Не знаю можно ли “область в которой ссылка действительна” трактовать как “область в которой заимствование действительно”?

Хотя дальше есть пара примеров, в комментариях которых говорится что длительность заимствования равна выбранному времени жизни:

Пример 1:

fn as_str<'a>(data: &'a u32) -> &'a str {
    'b: {
        let s = format!("{}", data);
        return &'a s
    }
}

fn main() {
    'c: {
        let x: u32 = 0;
        'd: {
            // An anonymous scope is introduced because the borrow does not
            // need to last for the whole scope x is valid for. The return
            // of as_str must find a str somewhere before this function
            // call. Obviously not happening.
            println!("{}", as_str::<'d>(&'d x));
        }
    }
}

Пример 2:

'a: {
    let mut data: Vec<i32> = vec![1, 2, 3];
    'b: {
        // 'b is as big as we need this borrow to be
        // (just need to get to `println!`)
        let x: &'b i32 = Index::index::<'b>(&'b data, 0);
        'c: {
            // Temporary scope because we don't need the
            // &mut to last any longer.
            Vec::push(&'c mut data, 4);
        }
        println!("{}", x);
    }
}
1 лайк