I'm working on a data pipeline node, an application that takes a continuous supply of data from stdin, processes it, and outputs the result continuously to stdout in a streaming fashion.
Considering the data interchange format is pre-determined, I need a handy way of barring my debug output from feeding to stdout simultaneously. Essentially, a global lock. True, I could just get rid of all the debug statements, but it's more of an academic exercise.
So let's make a function which can write to stdout, and locks stdout as long as it remains in scope so the type system itself prevents other places in the code from writing to 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(())
    }
}
Cool, a global lock on stdout that stays in place until the output push_output() function goes out of scope, but it doesn't work. I get a whole list of borrow checker errors:
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| |     }
  | |_____^
I've been trying for well over an hour to fix this sequence of borrow checker errors on these 7 lines of code. Here's a non-exhaustive list of steps I've taken so far that haven't worked:
- Change the lifetime of make_push_output
- Add explicit type and lifetime annotation to handle
- Declare a variable for io::stdout()and annotate with type and lifetime
- Add explicit type and lifetime annotation to the closure
- Declare a local function instead of using a closure, couldn't capture the environment
- Use movesemantics on the closure, not the brightest move, but I was grasping at straws
 
    