6
votes

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.

1
Note that this is only a problem because you are using println!, which takes a wide range of values. If you were to use the i value in some context that constrained the type (like by passing it to a function), then the type could be inferred.Shepmaster

1 Answers

10
votes

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.