Dialyzer ignores guard and reports an error with `-Wmissing_return`
Describe the bug
When using a guard such as when X =:= nil or when X =:= nil orelse orelse X =:= false, dialyzer is not able to eliminate the nil type from the integer() | nil return type and incorrectly complains about a missingnil type when turning on the -Wmissing_return flag.
To Reproduce
-spec foo(string()) -> integer().
foo(Text) ->
case one(Text) of
X when X =:= nil orelse X =:= false -> two(Text);
X -> X
end.
one("1") -> 1;
one(_) -> nil.
two("2") -> 2;
two(_) -> 0.
fails with
$ dialyzer -Wmissing_return foo.erl
foo.erl:4:2: The success typing for foo:foo/1 implies that the function might also return
'nil' but the specification return is
integer()
Expected behavior No error being raised.
Affected versions
26.2.1
Additional context
This bug is affecting truthiness checks in Elixir such as one(text) || two(text) (see https://github.com/elixir-lang/elixir/issues/13269).
Thanks for your report! We do not consider this a bug, when you ask dialyzer to go beyond its capabilities (e.g. by specifying -Wmissing_return or similar options), it may report things that cannot happen for reasons it's unable to infer.
You're essentially changing its mode from "only report things you know for certain" to "report things you think might be wrong," and warnings like these naturally arise from the latter.
That said, we may be able to fix this particular case. We'll look into it. :)