For example if I call "4".parse::<u32>() or "4".parse::<i32>(), how does it know which type's from_str() method to call using this single line > FromStr::from_str(self)?
The compiler will try to narrow it down if possible. If the compiler can't narrow it to a single type, a compilation error will be shown asking you, the developer, to disambiguate it.
It's type inference. The syntax FromStr::from_str(self) is a shorthand, the fully explicit notation for the function from_str of the implementation of a type Foo for the trait FromStr is <Foo as FromStr>::from_str(…).
In this case, the compiler does not know the right choice for the place where Foo stands in advance, so it's something of the form <??Unknown?? as FromStr>::from_str(…), but it knows the trait and the method,
where all occurrences of ??Unknown?? refer to the same not-yet-inferred type. If you match the return type, in this signature, which is the type of the expression FromStr::from_str(self), with the expected return type of the parse function, it thus knows to expect
Result<??Unknown??, ??Unknown??::Err>
to be the same type as
Result<F, F::Err>
so that, in the left type argument of the Result type, ??Unknown?? must clearly be F - mystery solved (type inferred)!
So, replacing the formerly unknown type, the call is thus ultimately <F as FromStr>::from_str(self).