3

I'm doing rust cli tutorials from https://rust-cli.github.io/book/tutorial/testing.html and got stuck with a compiler warning:

unused `std::result::Result` that must be used
  --> src/main.rs:15:13
   |
15 |             writeln!(writer, "{}", line);

Here is the whole code:

use exitfailure::ExitFailure;
use failure::ResultExt;
use structopt::StructOpt;

#[derive(StructOpt)]
struct Cli {
    pattern: String,
    #[structopt(parse(from_os_str))]
    path: std::path::PathBuf,
}

fn find_matches(content: &str, pattern: &str, mut writer: impl std::io::Write) {
    for line in content.lines() {
        if line.contains(pattern) {
            writeln!(writer, "{}", line);
        }
    }
}

#[test]
fn find_a_match() {
    let mut result = Vec::new();
    find_matches("lorem ipsum\ndolor sit amet", "lorem", &mut result);
    assert_eq!(result, b"lorem ipsum\n");
}

fn main() -> Result<(), ExitFailure> {
    let args = Cli::from_args();
    let content = std::fs::read_to_string(&args.path)
        .with_context(|_| format!("could not read file `{}`", &args.path.display()))?;
    find_matches(&content, &args.pattern, &mut std::io::stdout());
    Ok(())
}

Why do I get this warning?

taRusty
  • 101
  • 2
  • 8

1 Answers1

7

writer that you pass to writeln! can be arbitrary std::io::Write object, in particular a file writer, a network writer or whatever. Those can fail when you write to them and so writeln!(...) returns a Result<T,E>, which indicates whether write operation completed successfully or failed.

If you don't use this Result, then you can potentially miss when an error is occurred, so the logic of your program might fail then. (note that Rust doesn't have exceptions, so there are in general two ways of telling a problem: in a return type like Option, Result, bool, or whatever; or via panic!, assert! macros that will crash your program with no chance to recover if something went wrong).

So ideally you shouldn't ignore this Result in any way. You can do like this for now

for line in content.lines() {
    if line.contains(pattern) {
        if let Err(e) = writeln!(writer, "{}", line) {
            println!("Writing error: {}", e.to_string());   
        }
    }
}

If you wish, later on you can make a more adequate reaction to the error (like retrying writing)

Alexey S. Larionov
  • 6,555
  • 1
  • 18
  • 37