[][src]Attribute Macro proconio_derive::fastout

#[fastout]

Enables buffering for stdout.

You cannot create a closure containing print! or println! in #[fastout] function. This is because the closure cannot implement Send since StdoutLock, which is not a Send, is internally captured into the closure. This causes a trait bound mismatch when used with function requiring its argument closure to be a Send, such as std::thread::spawn().

This example deliberately fails to compile
use proconio::fastout;

use std::thread;

#[fastout]
fn main() {
   thread::Builder::new()
       .stack_size(32 * 1024 * 1024)
       .spawn(|| {
           println!("Hi!");
       })
       .unwrap()
       .join()
       .unwrap();
}

It is too conservative to make all of such closures compilation error because it is actually no problem to use such a closure only inside a single thread. However, since trait bound check is done after macro expansions, there is no way to check whther the closure is required to be a Send or not. And the compiler error message for actual mismatch of a Send requirement is too confusing, pointing out codes you didn't write (macro-expanded codes) as an error position. In conclusion, for user-friendliness, all of them are prohibited for now.

Internally this is the same with

let __proconio_stdout = ::std::io::stdout();
let mut __proconio_stdout = ::std::io::BufWriter::new(__proconio_stdout.lock());

#[allow(unused_macros)]
macro_rules! print {
    ($($tt:tt)*) => {
        <::std::io::BufWriter<::std::io::StdoutLock<'_>> as ::std::io::Write>::write_fmt(
            &mut __proconio_stdout,
            format_args!($($tt)*),
        )
        .unwrap()
    };
}

#[allow(unused_macros)]
macro_rules! println {
    () => {
        <::std::io::BufWriter<::std::io::StdoutLock<'_>> as ::std::io::Write>::write_all(
            &mut __proconio_stdout,
            b"\n",
        )
        .unwrap()
    };
    ($fmt:literal $($tt:tt)*) => {
        <::std::io::BufWriter<::std::io::StdoutLock<'_>> as ::std::io::Write>::write_fmt(
            &mut __proconio_stdout,
            format_args!(::std::concat!($fmt, "\n") $($tt)*),
        )
        .unwrap()
    };
}

let __proconio_res = {
    // Your code goes here
};
<::std::io::BufWriter<::std::io::StdoutLock> as ::std::io::Write>::flush(
    &mut __proconio_stdout
).unwrap();
return __proconio_res;