An easy answer to questions like “why Dialyzer isn’t ...” is “because it was designed to always be correct” or “because it never promises that it will catch everything or something specific”.
For a more complex answer, you need to additionally indicate your question. If I write your example in a module:
-module(bar). -export([myfun1/1, myfun2/1]). -spec myfun1(integer()) -> zero | one. myfun1(0) -> zero; myfun1(1) -> one; myfun1(2) -> other_number. -spec myfun2(integer()) -> zero | one. myfun2(0) -> zero; myfun2(1) -> one; myfun2(_) -> other_number.
And call him:
$ dialyzer bar.erl Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes Proceeding with analysis... done in 0m0.64s done (passed successfully)
... not a single discrepancy was found, because none of them is a "mistake." This is just the case when the code is in some ways more general (may return additional values) and in a sense more restrictive (cannot process every integer for version 1) than the specification.
The second version can be found using -Woverspecs :
$ dialyzer -Woverspecs bar.erl Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes Proceeding with analysis... bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero' done in 0m0.58s done (warnings were emitted)
The warning explains that the specification is more restrictive than the code.
Both problems can also be detected by the extremely unusual -Wspecdiffs :
$ dialyzer -Wspecdiffs bar.erl Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes Proceeding with analysis... bar.erl:5: Type specification bar:myfun1(integer()) -> 'zero' | 'one' is not equal to the success typing: bar:myfun1(0 | 1 | 2) -> 'one' | 'other_number' | 'zero' bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero' done in 0m0.61s done (warnings were emitted)
Neither the -Woverspecs mode nor the -Wspecdiffs is recommended, since type analysis of Dialyzer can and will generalize types, so “something defined in a more restrictive way” can be the result of generalization.
It may also happen that you intend for these functions to be called with only 0 and 1 as arguments, in which case the specification is ok.