rustc says: "error[E0282]: type annotations needed"
pub fn parse<T: std::str::FromStr>(v: &str) -> T {
match v.parse() {
Err(e) => {
panic!(
"Error when parsing to type {}. {} Value: '{}' ",
std::any::type_name::<T>(),
e.to_string(),
// Error: ^ cannot infer type
v
)
}
Ok(r) => r
}
}
Can I check whether the Error e implements Display and only then print it?
Calling .to_string()
here is redundant and causes an extra, unnecessary allocation compared to simply formatting e
. Remove the .to_string()
call, and add the bound T::Err: Display
.
Consider also formatting v
using debug formatting so that unprintable characters are displayed as escape sequences.
use std::{fmt::Display, str::FromStr};
pub fn parse<T>(v: &str) -> T
where
T: FromStr,
T::Err: Display,
{
match v.parse() {
Err(e) => {
panic!(
"Error when parsing to type {}. {} Value: {:?}",
std::any::type_name::<T>(),
e,
v
)
}
Ok(r) => r,
}
}
As far as why the error occurs, it's because the compiler doesn't yet know what type is being parsed. That is, when you call v.parse()
, the return type is not yet fully known. The compiler only knows that it must be Result<_, _>
. It becomes fully known when the Ok(r) => r
arm is seen; since r
is being returned from the function, the compiler can then infer that v.parse()
returns Result<T, T::Err>
, and therefore e
must be T::Err
.
Resolving that inference error is as easy as swapping the arms around so that the Ok
case is handled first. This way, the compiler knows what e
must be when e.to_string()
is reached. Fixing that error will reveal the missing Display
bound:
error[E0599]: `<T as FromStr>::Err` doesn't implement `std::fmt::Display`
This error could be fixed with the same where
clause provided above.