1 unstable release

0.1.0 Apr 7, 2020

#1948 in Procedural macros

MIT/Apache

6KB

Crates.io API reference

Versuch

Procedural macro polyfill for Ok-wrapping functions.

use versuch::try_fn;

#[try_fn]
fn word_count(path: &Path) -> io::Result<usize> {
    let mut res = 0;
    let file = fs::File::open(path)?;
    let mut reader = io::BufReader::new(file);
    for line in reader.lines() {
        let line = line?;
        res += line.split_whitespace().count();
    }
    res
}

This is a polyfill for the following imaginary syntax:

fn word_count(path: &Path) -> io::Result<usize> try {
    let mut res = 0;
    let file = fs::File::open(path)?;
    let mut reader = io::BufReader::new(file);
    for line in reader.lines() {
        let line = line?;
        res += line.split_whitespace().count();
    }
    res
}

lib.rs:

Procedural macro polyfill for Ok-wrapping functions.

Try blocks are a nightly rust feature for introducing less-than-a-function boundary ? operator. One notable feature of try-blocks as currently implemented is ok-wrapping:

let x: Option<i32> = try { 92 };
assert!(x.is_some());

That is, try { expr } desugars to, roughtly, (|| Try::from_ok(expr))().

Crucially you still have to use ? to propagate erors, but you don't have to wrap the final value in Ok. Moreover, if the final value is already a Result, you need to add an extra ?, to make the errors even more explicit than without ok-wrapping.

The try-block syntax naturarly generalizes to functions:

fn word_count(path: &Path) -> io::Result<usize> try {
    let mut res = 0;
    let file = fs::File::open(path)?;
    let mut reader = io::BufReader::new(file);
    for line in reader.lines() {
        let line = line?;
        res += line.split_whitespace().count();
    }
    res
}

Unfortunatelly, we can't have exact that even with proc-macros, but this crate provides something close enough:

use versuch::try_fn;

##[try_fn]
fn word_count(path: &Path) -> io::Result<usize> {
    let mut res = 0;
    let file = fs::File::open(path)?;
    let mut reader = io::BufReader::new(file);
    for line in reader.lines() {
        let line = line?;
        res += line.split_whitespace().count();
    }
    res
}

This crate is very much inspired by the https://crates.io/crates/fehler crate.

Disclaimer: this crate is a proc macro and thus can measurably increase the number of dependencies and compile times. It also breaks IDE support (sorry for that, @matklad).

Dependencies

~1.5MB
~34K SLoC