Я работаю над узлом конвейера данных, приложением, которое непрерывно передает данные из stdin
, обрабатывает их и непрерывно выводит результат в stdout
в потоковом режиме.
Учитывая, что формат обмена данными предопределен, мне нужен удобный способ запретить вывод результатов отладки одновременно с передачей на стандартный вывод. По сути, глобальная блокировка. Правда, я мог бы просто избавиться от всех отладочных утверждений, но это скорее академическое упражнение.
Итак, давайте создадим функцию, которая может записывать в stdout
и блокировать stdout
, пока она остается в области видимости, поэтому сама система типов предотвращает запись других мест в коде в stdout
:
use std::io::{self, Write};
pub fn make_push_output<'a>() -> &'a impl Fn(String) -> io::Result<()> {
let handle = io::stdout().lock();
&|output: String| {
handle.write(output.to_string().as_bytes())?;
Ok(())
}
}
Классно, глобальная блокировка на stdout
, которая остается на месте до тех пор, пока выходная функция push_output()
не выйдет из области видимости, но не работает. Я получаю полный список ошибок проверки заимствования:
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:4:18
|
4 | let handle = io::stdout().lock();
| ^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
|
= note: borrowed value must be valid for the static lifetime...
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ______^
7 | | handle.write(output.to_string().as_bytes())?;
8 | |
9 | | Ok(())
10 | | }
| |_____^ temporary value does not live long enough
11 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 3:25...
--> src/lib.rs:3:25
|
3 | pub fn make_push_output<'a>() -> &'a impl Fn(String) -> io::Result<()> {
| ^^
error[E0373]: closure may outlive the current function, but it borrows `handle`, which is owned by the current function
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ^^^^^^^^^^^^^^^^ may outlive borrowed value `handle`
7 | handle.write(output.to_string().as_bytes())?;
| ------ `handle` is borrowed here
help: to force the closure to take ownership of `handle` (and any other referenced variables), use the `move` keyword
|
6 | &move |output: String| {
| ^^^^^^^^^^^^^^^^^^^^^
error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
--> src/lib.rs:7:9
|
7 | handle.write(output.to_string().as_bytes())?;
| ^^^^^^
|
help: consider changing this closure to take self by mutable reference
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ______^
7 | | handle.write(output.to_string().as_bytes())?;
8 | |
9 | | Ok(())
10| | }
| |_____^
Я уже более часа пытаюсь исправить эту последовательность ошибок проверки заимствования в этих 7 строках кода. Вот неполный список шагов, которые я предпринял до сих пор, но которые не сработали:
- Изменить время жизни
make_push_output
- Добавить явную аннотацию типа и времени жизни к
handle
- Объявление переменной для
io::stdout()
и аннотирование с типом и временем жизни
- Добавить явную аннотацию типа и времени жизни к закрытию
- Объявить локальную функцию вместо использования замыкания, не удалось захватить среду
- Используйте
move
семантику на замыкании, не самый яркий ход, но я цеплялся за соломинку