Dialyzer doesn’t really know how foo/1 is called so it can’t do a better check than before. Try adding some code which calls foo/1 or inc/1 with explicit values, some good and some bad. As @NobbZ was pointing out is that success typing checks both sides working together, so it checks whether the values in a call will match the values expected in the definition.
And, shh, in many ways dialyzer actually ignores the type specs when doing the checking. It will find the same errors wit or without them, though it can give better error messages if they are there.