62
задан 23 June 2018 в 00:36

1 ответ

Является самым легким понять то, что нелексическое время жизни путем понимания, каково лексический время жизни. В версиях Ржавчины, прежде чем присутствует нелексическое время жизни, этот код перестанет работать:

fn main() {
    let mut scores = vec![1, 2, 3];
    let score = &scores[0];
    scores.push(4);
}

компилятор Ржавчины видит, что scores одолжен score переменная, таким образом, это запрещает дальнейшую мутацию scores:

error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable
 --> src/main.rs:4:5
  |
3 |     let score = &scores[0];
  |                  ------ immutable borrow occurs here
4 |     scores.push(4);
  |     ^^^^^^ mutable borrow occurs here
5 | }
  | - immutable borrow ends here

Однако человек может тривиально видеть, что этот пример чрезмерно консервативен: score , никогда не использовал ! Проблема состоит в том, что одалживание [1 111] [1 112] лексически —, это длится до конца блока, в котором это содержится:

fn main() {
    let mut scores = vec![1, 2, 3]; //
    let score = &scores[0];         //
    scores.push(4);                 //
                                    // <-- score stops borrowing here
}

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

А замечательная вещь о нелексическом времени жизни состоит в том, который когда-то включил, никто никогда не будет думать о них . Это просто станет, "что делает Ржавчина", и вещи будут (надо надеяться), просто работать.

, Почему лексическое время жизни было позволено?

Ржавчина предназначается, чтобы только позволить известный - безопасные программы компилировать. Однако это невозможно , чтобы точно позволить только [1 132] безопасные программы и отклонить небезопасные. С этой целью Ржавчина допускает ошибку на стороне того, чтобы быть консервативным: отклоняются некоторые безопасные программы. Лексическое время жизни является одним примером этого.

Лексическое время жизни было очень легче реализовать в компиляторе, потому что знание блоков "тривиально", в то время как знание потока данных меньше. Компилятор должен был быть переписан, чтобы представить и использовать "промежуточное представление среднего уровня" (MIR) . Затем одалживать средство проверки (иначе "borrowck") должно было быть переписано для использования MIR вместо абстрактного синтаксического дерева (AST). Затем правила одалживать средства проверки должны были быть усовершенствованы, чтобы быть с более прекрасными зернами.

Лексическое время жизни не всегда мешает программисту, и существует много способов работать около лексического времени жизни, когда они делают, даже если они являются раздражающими. Во многих случаях, этот включенные добавляющие дополнительные фигурные скобки или булево значение. Эта позволенная Ржавчина 1.0, чтобы поставляться и быть полезной много лет перед нелексическим временем жизни была реализована.

Интересно, бесспорный хороший шаблоны были разработаны из-за лексического времени жизни. Главный пример мне entry шаблон . Этот код сбои перед нелексическим временем жизни и компиляциями с ним:

fn example(mut map: HashMap<i32, i32>, key: i32) {
    match map.get_mut(&key) {
        Some(value) => *value += 1,
        None => {
            map.insert(key, 1);
        }
    }
}

Однако этот код неэффективен, потому что он вычисляет хеш ключа дважды. Решение, которое было создано , потому что из лексического времени жизни короче и более эффективен:

fn example(mut map: HashMap<i32, i32>, key: i32) {
    *map.entry(key).or_insert(0) += 1;
}

имя "нелексическое время жизни" не звучит правильным мне

, время жизни значения является отрезком времени, во время которого значение остается в определенном адресе памяти (см. Почему can' t я храню значение и ссылку на то значение в той же структуре? для более длительного объяснения). Функция, известная как нелексическое время жизни, не делает изменение время жизни никаких значений, таким образом, это не может сделать время жизни нелексическим. Это только делает отслеживание, и проверка одалживает тех более точных значений.

А более точное название функции могло бы быть "нелексически , одалживает ". Некоторые разработчики компилятора обращаются к базовому "основанному на MIR borrowck".

Нелексическое время жизни никогда не предназначалось, чтобы быть "стоящей с пользователем" функцией, по сути . Они главным образом стали большими в наших умах из-за небольшого papercuts, который мы получаем от их отсутствия. Их имя было главным образом предназначено во внутренних целях разработки, и изменение его для маркетинга целей никогда не было приоритетом.

Да, но как я использую его?

В Ржавчине 1.31 (выпущенный 06.12.2018), необходимо подписаться к выпуску Ржавчины 2018 года в Cargo.toml:

[package]
name = "foo"
version = "0.0.1"
authors = ["An Devloper <an.devloper@example.com>"]
edition = "2018"

С Ржавчины 1.36, выпуск Ржавчины 2015 года также включает нелексическое время жизни.

текущая реализация нелексического времени жизни находится в "режиме миграции". Если NLL одалживают передачи средства проверки, компиляция продолжается. Если это не делает, предыдущие одалживают средство проверки, вызывается. Если старые одалживают средство проверки, позволяет код, предупреждение печатается, сообщая Вам, что Ваш код, вероятно, прервет будущую версию Ржавчины и должен быть обновлен.

В ночных версиях Ржавчины, можно подписаться к вынужденной поломке через значение параметра:

#![feature(nll)]

можно даже подписаться к экспериментальной версии NLL при помощи флага компилятора -Z polonius.

образец А настоящих проблем, решенных нелексическим временем жизни

90
ответ дан 31 October 2019 в 14:18