I searched quite a bit and couldn't find a similar question, so here we go:
I'm writing a function that has a generic in the argument as well as the return. I understand that when a generic is in the return, the caller must supply it. What I don't understand is why the caller seemingly must also provide the generic for the argument?
A dummy example below which takes anything that implements AsRef<str>
, and attempts to parse it as an unsigned integer. Working playground
fn parse_as_int<N, S>(key: S) -> Result<N, ParseIntError>
where
N: FromStr<Err = ParseIntError> + Unsigned,
S: AsRef<str>,
{
let key = key.as_ref();
key.parse()
}
The above function produces the error:
5 | fn parse_as_int<N, S>(key: S) -> Result<N, ParseIntError>
| ^^^^^^^^^^^^ - -
help: add missing generic argument
|
16 | let _ = parse_as_int::<u8, _>("8");
The suggestion to use <u8, _>
works but is fairly ugly and unfriendly from the caller side. Why do we have to do this?
Something that does work is to use impl AsRef<str>
in the argument position, which also makes things simpler for the caller since they only need to provide the return type. But this confuses my understanding of syntactic sugar since I thought impl Trait
was syntactic sugar for generics!
So I guess my other question is: When should I use impl Trait
vs. a generic in this situation?
fn parse_as_int<N>(key: impl AsRef<str>) -> Result<N, ParseIntError> ...