При возврате результата использования StdinLock, почему был сохранен заем для stdin?
Дана следующая функция:
use std::io::{BufRead, stdin};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
}
Это не компилируется со следующей ошибкой:
error: `stdin` does not live long enough
--> src/main.rs:12:1
|
7 | let stdinlock = stdin.lock();
| ----- borrow occurs here
...
11 | }
| ^ `stdin` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Я нахожу это удивительным, потому что результат использования блокировки (через lines
) не сохраняет никаких ссылок на первоисточник. На самом деле, назначение того же результата привязке перед возвратом работает просто отлично ( Playground).
fn bar() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
let r = stdinlock
.lines()
.count();
r
}
Это говорит о том, что немедленное возвращение "использованной блокировки" привело к тому, что блокировка попыталась жить дольше, чем заблокированный контент, во многом необычным образом. Все ссылки, на которые я смотрел, обычно указывают на то, что порядок объявления имеет значение, но не то, как возвращаемые объекты могут влиять на порядок их выпуска.
Так почему же первая функция отклонена компилятором? Почему замок удерживается дольше, чем ожидалось?
2 ответа
Кажется, это ошибка в компиляторе. Вы можете сделать компилятор счастливым, используя явный return
заявление:
use std::io::{stdin, BufRead};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
return stdinlock
.lines()
.count();
}
fn main() {}
Как упомянуто в комментариях, есть несколько проблем Rust, связанных с этим:
Я не могу ответить на вопрос " почему", но могу сказать, что текущая реализация нелексических времен жизни 1 позволяет компилировать исходный код:
#![feature(nll)]
use std::io::{BufRead, stdin};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
}
1 1.25.0-nightly (2018-01-11 73ac5d6)