Propagate trait and the ability to propagate "success" (for some definition of success) (yeah we're back at not calling it Try)

This can be used in any case where your function:

  1. calls a function which returns a Result
  2. the success can be returned immediately
  3. the error can be handled before returning from the function

For example:

use std::path::Path;

use std::io::Result;
use std::io::ErrorKind;

use std::fs::File;

/// [r]eturn [s]uccess
macro_rules! rs {
    ($t:expr) => { 
        // <omitted>
        // NOTE: do we `Ok` wrap the success??
    }
}

fn open_or_create_file(path: impl AsRef<Path>) -> Result<File> {
    let error = rs!(File::open(&path));

    match error.kind() {
        ErrorKind::NotFound => File::create(path),
        _ => Err(error),
    }
}

Not to distract from your more general observation, but this code set off my TOCTOU race alarm, and on looking deeper, it's worse than that: this returns a File that is either read-only or write-only, but the caller has no good way of knowing which (call a Read method and see if it fails, I guess?) Shouldn't this be more like

fn open_or_create_file(path: impl AsRef<Path>) -> Result<File> {
    OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(path)
}

?

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.