7

I'm trying to write to standard output using the writeln!() instead of the println!() macro, so I can handle I/O errors (e.g. when I pipe long-running output to head) gracefully. I found the following snippet at https://rust-cli.github.io/book/tutorial/output.html#a-note-on-printing-performance, wrapped up here in an error handling function:

use std::io;

fn main() {
    if let Err(error) = run() {
        eprintln!("{}", error);
    }
}

fn run() -> Result<(), io::Error> {
    let stdout = io::stdout(); // get the global stdout entity
    let mut handle = io::BufWriter::new(stdout); // wrap that handle in a buffer
    writeln!(handle, "foo: {}", 42)?; // add ? if you care about errors here
    return Ok(());
}

It works on the website "run this code" button, but when I try to build it for myself, I get a compiler error:

error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<std::io::Stdout>` in the current scope
    --> src/main.rs:12:5
     |
12   |     writeln!(handle, "foo: {}", 42)?; // add ? if you care about errors here
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<std::io::Stdout>`
     | 
    ::: /home/hwalters/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/mod.rs:1516:8
     |
1516 |     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
     |        --------- the method is available for `std::boxed::Box<std::io::BufWriter<std::io::Stdout>>` here
     |
     = help: items from traits can only be used if the trait is in scope
     = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
     |
1    | use std::io::Write;
     |

Going on the "the method is available for..." hint, I tried wrapping the BufWriter in a Box, but this did not make any difference.

I'm using Rust 2018. Is there something I'm missing?

2 Answers 2

7

You need to import the std::io::Write trait as the error suggests:

use std::io::Write;

In Rust traits must be imported to be able to use the methods they implement.


It works on the website "run this code" button, but when I try to build it for myself, I get a compiler error:

If you're referring to the "A note on printing performance", which you link to, then it does include the import in the form of use std::io::{self, Write};.

1
  • Thanks. CLion is not as good at suggesting missing imports as IntelliJ! And I had apparently failed to read the error text carefully enough. (-: Commented Dec 11, 2020 at 18:17
2

The writeln! macro requires that its first argument has a write_fmt method. By default, io::BufWriter<T> doesn't implement this method, it's only implemented for io::BufWriter<T: io::Write> so to get access to the implementation you have to import the io::Write trait into your code. Fixed example:

use std::io;
use std::io::Write; // need to import this trait

fn main() {
    if let Err(error) = run() {
        eprintln!("{}", error);
    }
}

fn run() -> Result<(), io::Error> {
    let stdout = io::stdout();
    let mut handle = io::BufWriter::new(stdout);
    writeln!(handle, "foo: {}", 42)?;
    Ok(())
}

playground

Not the answer you're looking for? Browse other questions tagged or ask your own question.