Время жизни временной переменной ржавчины в цепочке методов - PullRequest
4 голосов
/ 22 марта 2019

Я пытаюсь выучить правила жизни Rust, сравнивая их с аналогичными понятиями в C ++, с которыми я больше знаком.Большую часть времени моя интуиция работает очень хорошо, и я могу понять смысл правила.Однако в следующем случае я не уверен, правильно ли я понимаю.

В Rust время жизни временного значения - это конец его оператора, за исключением случаев, когда последнее временное значение связано симя с использованием let.

struct A(u8);
struct B(u8);

impl A {
    fn get_b(&mut self) -> Option<B> {
        Some(B(self.0))
    }
}

fn a(v: u8) -> A {
    A(v)
}

// temporary A's lifetime is the end of the statement
// temporary B binds to a name so lives until the enclosing block
let b = a(1).get_b();

// temporary A's lifetime is the end of the statement
// temporary B's lifetime extends to the enclosing block,
// so that taking reference of temporary works similar as above
let b = &a(2).get_b();

Если временное значение находится в состоянии if, то согласно ссылке время жизни ограничивается условным выражением.

// Both temporary A and temporary B drops before printing some
if a(3).get_b().unwrap().val <= 3 {
    println!("some");
}

Теперь к вопросу:

Если поместить let в if условие, из-за сопоставления с образцом мы привязываемся к внутренней части временного значения.Я ожидал бы, что временное значение, ограниченное let, будет расширено на вмещающий блок, в то время как другие временные значения все еще должны иметь время жизни, ограниченное условием if.

(В этом случае фактически всеКопируется, я бы сказал, что даже временный B может быть отброшен, но это отдельный вопрос.)

Тем не менее, оба времени жизни расширены до включающего блока if.

// Both temporary A and temporary B's lifetime are extended to the end of the enclosing block,
// which is the if statement
if let Some(B(v @ 0...4)) = a(4).get_b() {
    println!("some {}", v);
}

Должно ли это считаться несоответствием в Rust?Или я неправильно понимаю, и существует непротиворечивое правило, которое может объяснить это поведение?

Пример полного кода:

Обратите внимание, что вывод в Rust

some 4
Drop B 4
Drop A 4

, в то время как вывод в C ++

Drop A 4                                                                                                                                                                         
some 4                                                                                                                                                                           
Drop B 4

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

Обновление:

Неясно, почему правило временного срока действия if условного выражения не применяется к if let.Я думаю, что let Some(B(v @ 0...4)) = a(4).get_b() должно быть условным выражением, и, следовательно, время жизни временного A должно быть ограничено этим, а не всем оператором if.

Поведение продления времени жизни временного B до всего *Ожидается выражение 1064 *, поскольку оно заимствовано при сопоставлении с образцом.

1 Ответ

6 голосов
/ 22 марта 2019

Конструкция if let является просто синтаксическим сахаром для конструкции match.let Some(B(v @ 0...4)) = a(4).get_b() не является условным выражением, используемым в регулярном выражении if, поскольку оно не является выражением, которое оценивается как bool.Учитывая ваш пример:

if let Some(B(v @ 0...4)) = a(4).get_b() {
    println!("some {}", v);
}

Он будет вести себя точно так же, как в этом примере.Без исключений.if let переписывается в match до того, как даже будут запущены контролеры типа или заимствования.

match a(4).get_b() {
    Some(B(v @ 0...4)) => {
        println!("some {}", v);
    }
    _ => {}
}

Временные символы живут так же долго, как и в блоках совпадений, потому что они иногда оказываются полезными.Например, если ваша последняя функция была fn get_b(&mut self) -> Option<&B>, и если временная функция не существовала для всего блока сопоставления, она не прошла бы заем.

Если условные выражения не следуют тому же правилу, потому что это невозможнодля последнего вызова функции в условном условии if для сохранения ссылки на что-либо.Они должны оценить равнине bool.

См .:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...