I have this generic function in my Rust code:
fn test<T>(text: &str) -> T {
text.parse::<T>()
}
The idea is that the caller would do something like
test::<u64>("2313");
But the compilation fails with this message
error: the trait `core::str::FromStr` is not implemented for the type `T` [E0277]
I just started learning Rust yesterday, so this is probably a very basic question that I've failed to find the answer to.
Like the error message states, T needs to implement core::str::FromStr in order to be applicable for the parse function. The type signature of parse is:
fn parse<F>(&self) -> Result<F, F::Err> where F: FromStr
Which limits the sort of F (or, in your case T) you can use to those implementing FromStr. Your other problem is the type returned by test; it should be the same as the one of parse - a Result.
When you fix those issues, your function will work:
use std::str::FromStr;
fn test<T: FromStr>(text: &str) -> Result<T, T::Err> {
text.parse::<T>()
}
fn main() {
println!("{:?}", test::<u64>("2313"));
}
Ok(2313)
When you declare a generic type parameter T, you don't know anything about that type. It could be i32, String, () or PinkElephant; only two of those can be parsed from a string.
The way to restrict types in Rust is by trait bounds: we explicitly request a specific behavior from the type. Like "this type can be any type but I at least want the possibility to clone one instance of this type" (this would be the Clone trait). You can (and should!) read more about the topic of traits in the dedicated chapter in the Rust book.
So what feature do you expect from your type T? You want to create an instance of T from a string by using str::parse(). The function signature of parse() is:
fn parse<F>(&self) -> Result<F, F::Err>
where F: FromStr
It also takes this generic parameter F and bounds it with the trait FromStr. Thus, in order to use parse(), your type parameter T also needs to implement FromStr. Your function could look like this:
use std::str::FromStr;
fn test<T: FromStr>(text: &str) -> T {
text.parse::<T>().expect("string was invalid!")
}
What is this expect() you ask? Well... we are touching another topic here: error handling. There is also a chapter on that topic in the book, which you should read. In short: you need to somehow handle the case that the string was invalid (like "peter" when you were trying to parse an integer). expect() is probably the wrong way here: it just panics (aborts the thread) when the parsing did not succeed.
Also remember that there is a compiler error index, in which you can read more about a specific error. Here is the entry for your error E0277.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With