I have a non-generic function that works fine:
fn valid_i32(s: &str, minimum: i32, maximum: i32,
what: &str) -> Result<i32> {
let n: i32 = s.parse()?;
if minimum <= n && n <= maximum {
return Ok(n);
}
bail!("{} invalid or out of range", what)
}
But when I try to make a generic version that will work with any kind of number I keep getting problems. Here's the function in a complete tiny program:
#![recursion_limit = "1024"]
#[macro_use] extern crate error_chain;
extern crate num;
mod errors { error_chain!{ foreign_links {
Int(::std::num::ParseIntError); } } }
use errors::*;
use std::cmp;
use std::str;
quick_main!(run);
fn run() -> Result<()> {
let a = valid_num("123", 0, 255, "a");
let b = valid_num("245", -20, 20, "b");
println!("a={:?} b={:?}", a, b);
Ok(())
}
fn valid_num<T>(s: &str, minimum: T, maximum: T, what: &str) -> Result<T>
where T: num::Num + cmp::PartialOrd + Copy + str::FromStr {
let n: T = s.parse()?;
if minimum <= n && n <= maximum {
return Ok(n);
}
bail!("{} invalid or out of range", what)
}
And here's the error message:
Compiling validint v0.1.0 (file:///home/mark/validint)
error[E0277]: the trait bound `errors::Error: std::convert::From<<T as std::str::FromStr>::Err>` is not satisfied
--> src/main.rs:22:16
|
22 | let n: T = s.parse()?;
| ^^^^^^^^^^ the trait `std::convert::From<<T as std::str::FromStr>::Err>` is not implemented for `errors::Error`
|
= help: consider adding a `where errors::Error: std::convert::From<<T as std::str::FromStr>::Err>` bound
= note: required by `std::convert::From::from`
I tried it without error-chain but that was much worse. In general I find that error-chain works really well: providing you get the foreign-links right. And often I can't figure out what they should be.