Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type annotation in a pattern match in Rust?

Tags:

rust

I'm digging into Rust, specifically into gracefully handling errors, but I'm having a little trouble with type inference.

extern crate mysql;

use mysql as my;

fn main() {
    my_test();
}

fn my_test() -> Result<(), my::Error> {
    let pool = try!(my::Pool::new(""));
    let res = try!(pool.prep_exec("select 1 as count", ()));
    for rows in res {
        let row: my::Row = try!(rows);
        match row.take("count") {
            None => (),
            Some(i) => println!("{:?}", i),
        };
    }
    Ok(())
}

which leads to

src/bin/main.rs:86:12: 86:13 error: unable to infer enough type information about _; type annotations or generic parameter binding required [E0282]

Unfortunately the docs in that crate use unwrap a lot, which does not help me. In Haskell, I would do something like println!("{:?}", i :: i32), but I can't figure out how to do it in Rust. I've tried various ways to cast row.take, but I've haven't had any luck. I'd love to see a variety of ways in which I could have structured this code, if there is a more idiomatic way of going about it.

like image 202
David McHealy Avatar asked Jun 10 '16 19:06

David McHealy


2 Answers

Looking at Row::take documentation we can see two types parameter T and I. The type I is inferred from the "count" argument, the type T is used for the return type. We have two options to specify the return type, explicit in the method call, or implicit in type of a variable (like you did with row):

fn my_test() -> Result<(), my::Error> {
    let pool = try!(my::Pool::new(""));
    let res = try!(pool.prep_exec("select 1 as count", ()));
    for rows in res {
        let mut row: my::Row = try!(rows);
        // specify type T explicitly, let type I to be inferred
        match row.take::<i32, _>("count") {
            None => (),
            Some(i) => println!("{:?}", i),
        };
        // or
        let s: Option<i32> = row.take("count");
    }
    Ok(())
}

The type ascription RFC proposes a syntax (similar to the Haskell example) for annotating a sub-expression with a type.

like image 114
malbarbo Avatar answered Nov 13 '22 08:11

malbarbo


The types can be annotated on the Option<T> or Result<T, E> variants in the match pattern.

For Option,

match row.take("count") {
    None => (),
    Some::<i32>(i) => println!("{:?}", i),
}

Or if your function returns a Result,

match row.take("count") {
    Err(e) => panic!("{:?}", e),
    Ok::<i32, _>(i) => println!("{:?}", i),
}
like image 44
AaronDanielson Avatar answered Nov 13 '22 06:11

AaronDanielson